AxonIQ reposted this
Monoliths versus microservices. The debate should not be one versus the other. It's about finding the balance. Microservices come with a lot of additional complexity. The distributed nature of the system makes certain changes very difficult. The network alone is a place to be worried about. The less time you(r program) spend there, the better it is. There is a reason why the first rule of distributed systems is: don't! But monoliths... They are hard to maintain. They tend to grow large and become difficult to deploy. They don't scale. And ultimately, they turn into a Big Ball of Mud. Really? I disagree. You might think that separating our system into smaller, independently deployable units makes software more maintainable. That's partly true. Breaking it into smaller units is the way to go. But deploying them separately is not. The biggest challenge we face in separating our system into modules is that we don't know what the right module boundaries are. Based on experience, some boundaries may look absolutely obvious. But we need to face the fact that for most of the systems we build, we don't exactly know the specifications by the time it reaches production. As we build our system, we learn more about the domain. Meanwhile, the domain may even evolve, requiring our software to adapt. All these changes put tension on our boundaries. We may need to slightly shift them to put certain components that were originally seen as "separate" now need to be joined. Or vice versa. When our software is split into separate deployable units, moving components from one to another is no longer a simple refactoring. It becomes a major change that needs a complete deployment and deprecation lifecycle of API changes. A lot of effort for a conceptually simple change. How can we benefit from the flexibility of the monolith and the scalability and "fast flow" of microservices? Look for the middle ground. Between "one" and "thousands," a specific number must work well for you in your specific environment. Don't try to guess that number upfront. You'll get it wrong. And even if you do, the right number will change over time. Instead, allow your software to adapt. Build it so that components can be split into separate deployable units and combined back into one. Impossible? These components need to be "Location Transparent." Components are location transparent when they aren't aware of the relative location of the components they interact with. To achieve location transparency, define explicit messages. Define the commands, events, and queries (including their replies) that flow between these components. Transport these messages using a bus abstraction. When needed, the bus implementation will carry the messages over the network. When not, it will carry them locally to the right destination. In the diagram depicted below, the sweet spot is as far up as you can get and as far left as you can get away with.
Structure is a function of requirements. It's that simple. So, it all depends on devs understanding requirements and prioritizing them correctly.
Hi Allard (long time no see), thanks for your post! I don’t know when it will be published by KanDDDinsky conference, but we have made a talk recently Julien Topçu and I about all these problems too. We’ve presented another solution for them (a pattern we call « the Hive »), but it’s great to see other people talking about these issues 👍
It always comes down to how small a part is so it can be easily deployed in a new version. How many system depends in fast and easy deployment ? There must be thousands of smaller systems that don't benefit from fast deployment but more of consistency and stability and NOT scalability. A well designed "modular monolith" is perhaps the most useful strategi for this. Combine the benefits with the trad-offs and choose what seems to be the best for your organisation.
It seems like many organisations try to have the „best“ of both worlds by creating distributed monoliths. ;-)
Deploying them separately is a selling point for the cloud and if it's the right solution: go for it. Quite often it's not though.
I totally agree with you and your recommendations on this topic, Allard. In an organization with a diverse technology and application/system landscape, it's also very helpful establishing a canonical (message) model for the message transport you suggested, to further ease Data Integration & Interoperability between the various applications/systems.
Love this
Really nice overview of this huge debate!
Gerichtssachverständiger für Softwarequalität | damit Software einsetzbar ist und bleibt
2wSo basically you say, that one should design for the future - introduce location transparency when it is not needed (and introduces unnecessary code and complexity) because it might be needed in the future. IMHO that is bad advice. Why not make sure that the monolith is in fact a modulith (i.e. well structured monolith). Then your modulith is no big ball of mud, smaller, easier to deploy and easier to maintain than a microservice architecture. And it scales perfectly, just no different scaling at different parts (which is typically not needed).