When are microservices the wrong choice?

Cameron Tittle
Credera Engineering
6 min readApr 3, 2023
Photo by Christina Morillo: https://www.pexels.com/photo/close-up-photo-of-person-typing-on-laptop-1181675/

The microservices buzzword has been around for a number of years now. For many teams architecting a new system, adopting a microservices architecture is a no-brainer. Monoliths are a relic of the past and not suitable for production applications in this day and age — right?

In this blog, we’ll be taking a look at how microservices can sometimes be the wrong choice for your application architecture, including how they could be hindering your team’s delivery.

Microservices (All singing, all dancing)

We’ll keep this section short and sweet given that most people reading this will already know what microservices are. In a nutshell, we can divide an application into a set of (micro)services which are each responsible for a small portion of functionality. The services should be fine-grained (i.e. small) and should be divided based on business domains. This in turn helps services to be loosely coupled, meaning they should have minimal dependencies on each other.

Ideally, microservices should be independently deployable, meaning each can be owned by a single team. This allows for specialisation, where developers have a deep understanding of the service they are responsible for and allowing for faster debugging and development — in contrast to a shallow understanding of a large monolith system.

Microservices should aim to have ownership over as many of their dependencies as possible. For example, each should have its own data store that is not shared with any other service, giving it full control over where and how it stores data.

All of this is in aid of increased scalability, reliability, development velocity, and agility. Wonderful. So we’ve reached software utopia — what’s the catch?

Credit: Daniel Stori

Microservices from Hell

As with any theoretical architecture, it’s possible to implement microservices poorly. There are a number of symptoms that can present themselves in microservices-based systems which hint that all is not well. These anti-patterns tend to negate many of the benefits listed above - instead introducing additional tooling and overhead without tangible improvements in development velocity or system performance.

The distributed monolith

The distributed monolith is exactly how it sounds — a system which is deployed across multiple microservices but behaves like a monolith.

Here’s what to look out for:

  • Tightly coupled services: This is when services depend on each other for data or functionality, requiring lots of network calls between services. In a normal monolith, these requests would be low-latency function calls, whereas in a distributed monolith, these network calls incur a high time penalty and reduce the performance of the system. Another sign of tightly coupled services is when changes in one service require changes in multiple other services. This makes it hard for services to be built, deployed, and scaled independently.
  • Deploying every service, every time: One of the key drivers of microservices is the ability for teams to take ownership of a service and develop and deploy it independently of the other services in the system. This become difficult, nigh on impossible, if the release cycle and deployment of all services are tied together. We now have the complexity of deploying to tens or hundreds of separate targets and the overhead of managing the pipelines to do so, without any of the agility that microservices is supposed to provide.
  • Lack of fault tolerance: What happens if one of your services becomes unavailable? Can the end user still make use of the other parts of the application, or are they greeted with a blank page and an unhelpful error message? By separating functionality into separate services, the system should be able to cope with one non-essential service going down. If it can’t, this points once again to tightly coupled services which are overly dependent on each other — a classic symptom of the distributed monolith.
  • Homogenous tech stack: A big selling point for microservices is the ability to use different technologies and tooling for different parts of your system to best suit each service’s needs. For example, you may use a NoSQL database for one service and a relational for another, or even write some services in a completely different language. If all your services are using exactly the same technologies, you aren’t necessarily reaping the full benefits of the microservices architecture.

Distributed monoliths combine the worst aspects of microservices (distributed deployments, latency, tooling overheads) with the worst aspects of monoliths (large inter-dependent codebase, lack of fault tolerance, lack of fine-grained scaling).

One team, one thousand microservices

A big benefit of microservices is to do with the teams that build them. If you have a large selection of teams to build a system, it makes sense to carve up the system into smaller services that can each be owned by a team. Each team will have a deep understanding of their service and be able to develop and deploy their service in a manner — and to a schedule - that suits them.

However, it isn’t uncommon for a single team to build an entire system based on microservices, simply because that’s the correct architecture these days. In this scenario, the team is responsible for understanding, building, and deploying all aspects of the system. The specialisation benefit that microservices enables is lost.

“Premature optimisation is the root of all evil”

There may be valid reasons for an entire microservices system to be built by a single team, such as a desire for high scalability. Or perhaps the company expects to grow their engineering team in the future, so it makes sense to build the system with microservices from the get-go.

It’s easy to fall into the trap of premature optimisation, however. How many systems really need to handle hundreds of thousands of requests per second? For applications that plan to scale at some unspecified time in the future, it may be more sensible to build a monolith initially, with the option to split out parts of the system to scalable services later if those parts become bottlenecks. For some teams working in start-ups, for example, accepting this technical debt may be a worthwhile tradeoff if it allows them to get to market faster.

On the other hand, some companies have had great success by committing fully to the microservices architecture. The challenger bank Monzo invested time and capital early on to build an entirely new banking system comprising over 100 microservices, growing to over 1000 today. They were planning ahead for huge scale, and microservices gave them more agility than their traditional banking competitors. For Monzo, the investment paid off, as they now have over 5 million customers and are one of the UK’s largest challenger banks.

Long live the monolith

There is no doubt that microservices work extremely well for large, scalable systems being built and deployed by many separate teams. For many applications, a microservices architecture is absolutely a sensible choice.

However, teams should not immediately dismiss the option of building a monolith when their system is not overly complex, does not expect Netflix scale, and will not be managed by teams of teams. This may* allow teams to deliver value faster by reducing the overhead that microservices bring in terms of tooling, deployments, data consistency, and inter-service communication. (*But your mileage may vary!)

Additionally, teams that do choose to build with microservices should watch out for the symptoms of the distributed monolith discussed above. These could be a sign that despite the system being composed of microservices, they may not come to provide you with the scale, agility, and reliability when you need it. In this case, the architecture may in fact be hindering development more than helping it. As with many such topics in engineering, there is no silver bullet. The correct choice will depend on your team and your application’s requirements.

Interested in joining us?

Credera is currently hiring! View our open positions and apply here.

Got a question?

Please get in touch to speak to a member of our team.

--

--