Monoliths are bad... are they?


Some things happened recently that made me write this post:

I have to admit that when I was finishing my MSc and I was working at some company as a trainee, I didn’t know a thing about proper software design. I remember trying to model something that probably needed from an interface and several implementations with a generic Java collection. Probably I won’t never forget the face of my colleague, a senior developer (my first boss!), when he saw what I did. After some years, I earned some experience and I learned a few fancy things… DDD, SOLID, patterns and so on. But let’s face it, programming is hard whether you have the knowledge and experience or not. It’s hard to foresee all casuistics and do the perfect design, the perfect model or the perfect implementation. “How to split responsilibities properly?” “How do you know if you’re defining the proper method contracts?” “How to do a truly supple domain model?" Let’s be honest, sometimes we even struggle putting names to classes. This is completely normal, but depending on the affection, love and time that we put into the design and implementation, we can end with a nice codebase or a complete mess of spaghetti code.

Then, some day, someone decides that we need to move to microservices, because <Insert name of a cool company> did it. If it’s hard to program, if it’s hard to design, if it’s hard to have a nice codebase, imagine having to go a step further and do all of this but at a much bigger scale, by adding another step that requires to divide and seggregate responsibilities into different components. Entering the microservices world should make us understand that we need to address the hardest parts of programming to be able to answer the previous questions (and similar ones), but also we need to tackle the complexity of a distributed system. “How to split services properly?” “How to define proper service contracts so they can communicate?” “How can we adapt this to the domain model, where do I put this thing?” What happens with the resiliency? In a monolith you can call a method and that’s it, but what happens if a microservice is down? Do you propagate the error across everything? What strategy would you choose to avoid this? And what about SLAs? You need to take care of 50 applications that can make your whole system unresponsive. And the monitoring, how do you manage logs, for instance? And deployment and lifecycle management, how do you operate, configure, version and manage 50 services?

Don’t get me wrong, with this post I don’t mean that microservices are bad. But many many times this type of architecture is chosen as the de facto standard for everything. Or we even think that if we choose it we’re in the state of the art in terms of technology, or in a high degree of maturity in terms of someone’s DevOps standards. But the truth is, microservices is just another option. If it’s good or bad doesn’t depend on any maturity level, it just depends on your needs. If you’re building an email service or a project management software like the Basecamp team, maybe you don’t need them at all. It’s better to have a nice built monolith than having a crappy “distributed monolith”, disguised as a microservices architecture, in which every service is just a big ball of mud that has been splitted into different applications, with same degree of intercoupling as the monolith. But it’s cool because you’re using microservices! Then you discover that you perform a change in an entity and you need to update 60 services at same time for everything to work.

Then, you may ask me, “Okay, then in which scenario should I use microservices?". That’s for another blog post. 😇

See you and stay safe!

Cover by Patrick Tomasso on Unsplash