Skip to main content

On Microservices

· 7 min read
Software Engineer

This past week, I had a discussion with a student team about microservices. This is a topic I've wanted to write about for a while and given the immediate relevance to this team, I finally made it a priority.

The microservices architecture is a popular and growing trend in many technology organizations today. But its implementation is often met with unsurmountable challenges by unprepared teams. This article discusses some of the challenges of microservices and how to overcome them.

Microservices Concept

In their article, Microservices, James Lewis and Martin Fowler give the following definition:

The term "Microservice Architecture" has sprung up over the last few years to describe a particular way of designing software applications as suites of independently deployable services. While there is no precise definition of this architectural style, there are certain common characteristics around organization around business capability, automated deployment, intelligence in the endpoints, and decentralized control of languages and data.

In short, this means breaking down a large application into several smaller applications. Let's first consider an example and then talk about why we might do this. Suppose we begin with this example monolithic application use for taking and tracking customer orders.

In the diagram above, we have a conceptual application architecture in which we have a web application layer (a UI), an API layer (server-side business logic), and a database. In the monolithic example, all of the major functions of the application are housed in the API layer as one big program.

Microservices, on the other hand, break up this functionality into logically separate services. The diagram below shows a similar architecture in terms of functionality, but it splits the major functions into separate "microservices" each with their own data storage and API.

In this case, each major piece of functionality is broken down into its own microservice. When the services need to communicate with one another – for example, if the Order Placement service needs to talk to the the Payment Service, it does so via the Payment Service's API.

This creates a system where each service is smaller and defined by its API. In other words, as long as we keep the interfaces the same, we can change the underlying implementation of a service without the rest of the system needing to care.

Pros & Cons

While microservices are very popular these days, there are some trade-offs to a microservices architecture to be aware of and it's the drawbacks that are often times overlooked.

Benefits of Microservices

  • Individual services are small and simple, manageable by smaller teams. Each service could be as small as a few thousand lines of code.
  • System reliability can be increased because a service outage doesn't take down the whole system. We can also scale service individually depending on usage.
  • Flexible implementation because of HTTP based interservice communication. This allows services to use the technologies that make sense for their function independent of other components.

Drawbacks of Microservices

  • Overall system complexity is increased. Interservice communication forces interfaces between microservices to remain consistent or backward compatible.
  • Increased overhead - versioning control, continuous integration, testing, and deployments need to be handled for each services drastically increasing that overhead.
  • Increased staffing need due to overhead. All the additional system complexity and engineering overhead means you need more people to build the same amount of functionality.

There is a strong case for microservices in many cases, but teams that overlook these drawbacks can be unprepared to handle them. In the next section, we'll go over the pitfalls that teams run into and how to avoid them.

Avoiding Pitfalls

The most common microservices pitfall I've seen is overlooking the increase in system complexity. Most people approach microservices with the idea that because it's "micro" it is simpler. And, while this is true that each service is simpler than a large monolithic application, the overall system is generally much more complex.

Clear interfaces need to be defined for each service, those interfaces need to remain consistent or backwards compatible, and breaking changes to those interfaces need to be well understood across teams. This ultimately means a well defined architecture needs to be present. The architect needs to be engaged in managing this complexity and ensuring the architecture is well understood across the organization.

Logical flow of system functions needs to be understood as well. Failure to thing about system behavior often leads to using interservice APIs as trivially as function calls, introducing a complex web of interservice dependencies making many services critical to common workflows and thus adding more points of failure. This can have the opposite effect of the intended increased reliability deriving from a microservices architecture.

This complexity feeds directly into the other two pitfalls – failure to prepare for the added overhead and understaffed engineering teams.

To prepare for the added overhead, we need to recognize that while a microservice's source code may be small, it requires significant overhead. Each services needs its own versioning and branching strategy, release strategy, CI/CD pipelines, automated testing, redundancy, and scaling. This means that a "small" services require a lot of additional code or DevOps work to support them.

Dealing with this means planning for it. It means ensuring that every engineer understands those DevOps pieces and even the smallest teams are capable of handling those aspects of a services independently.

As these get overlooked, the common result is understaffed teams. When we think about microservices as being "micro", managers frequently assign a single person to manage one or more microservices. There are a lot of definitions out there for how big a microservices should be – it's not well defined.

How big is a microservice?

Some people think a microservice should be small enough for a single person. In my opinion that's impractical once you account for the additional overhead. The other concern is that when an individual builds something is isolation is tends to be far worse than when design with collaboration. My view is that one team should own one service. In some cases it might be okay for a team own 2-4 small services depending on how much context switching that introduces. It could be a small team, but it limits context switching and ensures adequate resources are allocated to a project.

Effective Microservices

In my experience there are two key things needed for effective microservices implementations. The first a strong understanding over the overall system architecture – which becomes critical as complexity increases. The second is a sufficient understanding of the human and infrastructure resource needs introduced by that complexity and proper allocation of those resources.

While microservices is a growing trend, it doesn't make sense for every organization. Understanding these trade-offs will help your organization know if and when microservices make sense for you.

Further Reading

  • Fundamentals of Software Architecture by Mark Richards and Neal Ford – This book covers a wide range of architectural concepts, including microservices, and the trade-offs betweens different approaches. A must-read for any software systems architect.
  • Microservices by James Lewis and Martin Fowler – This is one of the best introductory articles I've read on the topic of microservices.
  • Microservices Guide by Martin Fowler – This is a collection of articles by on microservices and related topics. An excellent resource for diving deeper into this topic.