The microservice architecture is meant to simplify and accelerate development, but only when done correctly

anti-patterns   architecture   microservice architecture   developer experience  

A key goal of the microservice architecture is to accelerate development by improving the developer experience. For example, let’s imagine that you are a member of the Delivery Management team, responsible for developing the delivery management subdomain of the FTGO application. Your focus is on developing the very best courier scheduling algorithm so that your company can maximize consumer satisfaction and beat its competitors in a very cut throat market. Anything that slows down development could jeopardize the very existence of the company. The challenge, of course, is that scheduling deliveries is a complex subdomain. There’s no right answer and the only way to make progress is to constantly iterate and experiment. To do that, you need to be able to frequently make changes, deploy them into production and get feedback.

In this article, I describe why using the microservice architecture can accelerate software delivery. You will learn about two common architectural smells that can have the opposite effect and slow down development. I’ll also describe how it’s insufficient to simply adopt microservices. You also need to adopt the right development practices and team structure.

Let’s start by looking why the monolithic architecture is not always the best choice.

A monolithic architecture can sometimes slow you down

There’s nothing inherently wrong with the monolithic architecture. But for a company such as FTGO, which has many teams working on a very large application using practices such as DevOps and continuous deployment, a monolithic architecture can be an obstacle to the rapid development. In particular, it can be challenging to resolve the dark energy forces, which can result in various problems including:

  • Lack of team autonomy - Team autonomy can suffer because teams regularly have to coordinate their changes.
  • Slow deployment pipeline - Implementing a fast deployment pipeline that can support a high rate of pushes/PRs (e.g. at least once per developer per day) without becoming a bottleneck can be challenging, if not impossible, due to the application’s size and complexity
  • Difficult to change the technology stack - Changing or upgrading the application’s technology stack is especially difficult because it requires all teams to upgrade at the same time.

These issues are especially problematic if you are developing a subdomain, such as delivery management, that requires frequent experimentation.

Using microservices should accelerate development

It often makes sense, therefore, to implement subdomains, such as Delivery Management, that need rapid iteration, as separate services.

For the Delivery Management team, there are several advantages to having a Delivery Service including:

  • Improved team autonomy - the Delivery Management team can develop, build, test and deploy the service independently of what other teams are doing
  • Faster deployment pipeline - the Delivery Service is significantly smaller than the overall application and the rate of commits is much lower so its unlikely to be a bottleneck.
  • Easier technology stack management - the Delivery Management team can make decisions about technologies, e.g. library versions, without having to coordinate with the rest of the organization.

A standalone Delivery Service enables the Delivery Management team to focus on the courier scheduling algorithm and frequently run experiments to improve it. The team will have less cognitive load, more autonomy and get faster feedback from production. Or, at least it should but ….

But you need a well-designed microservice architecture

Sadly, using “a bunch of services”, which superficially resembles a microservice architecture isn’t guaranteed to accelerate development. The architecture needs to be well designed. There are two common architecture smells that can hinder development:

  • Tightly coupled services
  • Excessively fine-grained architecture

Let’s look at each smell in turn.

Tight design-time coupling will kill productivity

One common mistake is to ignore the essential concept of design-time coupling and create services that are tightly coupled to each other. If, for example, the Delivery Service is tightly coupled to other services then the productivity of the Delivery Management team will suffer since they will frequently need to coordinate with other teams. Either the Delivery Management team will constantly be blocked waiting for other teams to make the necessary changes to their services. Or, they will be frequently changing their service to support changes in other services.

Analyze Git commits to detect tight design-time coupling

One way to detect tight design-time coupling is to analyze Git commits to identify services that frequently change in lock step. If you regularly see JIRA (for example) issues that are implemented by commits for the same group of services, then that’s an indication of tight design-time coupling. For example, the CodeScene documentation describes how to detect design-time coupling (what it calls change coupling) in more detail.

Refactor to eliminate tight design-time coupling

Let’s imagine, for example, that the Delivery Service and the Order Service, which is owned by a different team, regularly change together. One solution would be to merge the two services, which simplifies development although might not address team autonomy.

Another option, would be to reassign responsibilities and redefine APIs to reduce the degree of coupling. For example, in QConPlus 2021: Takeout burritos and minimizing design-time coupling in a microservice architecture, I described how moving the calculation of an order’s subtotal from the Order Service to the Restaurant Service reduced design-time coupling between the two services.

An excessively fine-grained architecture can also slow you down

Tight design-time coupling isn’t the only architectural smell. Another issue an excessively fine-grained architecture, the More the Merrier anti-pattern. That’s because the more fine-grained an architecture, the more complexity it has in the interactions between services. When done right it can, as I described earlier, simplify development since the services are simpler. But if you take it too far, then instead of being able to focus on business logic you will find yourself spending too much on writing collaboration logic.

Instead of being able to focus on business logic, you will constantly implement the service collaboration patterns: Saga, API Composition, and CQRS.

At most one service-per-team is a reasonable goal

But one rough rule of thumb is that a Service per Team is a reasonable goal. And that the, all too common, one service per developer architecture is probably too fine-grained.

Design a better microservice architecture using Assemblage

Designing a better microservice architecture is difficult and involves numerous trade-offs. A good approach is to use the Assemblage architecture definition process that uses the dark energy and dark matter forces to shape the architecture.

You also need the rest of the success triangle

Simply adopting the microservice architecture isn’t enough to accelerate development. You also need to adopt the other two elements of the success triangle: DevOps as defined by the DevOps handbook; and an organization structure consisting of small, loosely coupled teams, as described by Team Topologies.

Ignoring those two elements is a common anti-pattern of microservice adoption.

Is your microservice architecture helping or hindering development?

There are a couple of ways to answer this question:

  • Ask the developers
  • Gather the DORA metrics

Survey the developers

A good way to determine whether a microservice architecture is helping or hindering development is to ask the developers using a survey. For example, the DORA DevOps survey includes questions, such as “Complete their work without communicating and coordinating with people outside their team”, which is a characteristic of high-performance teams. You can also ask questions about ease of making changes; and how much time is spent on business logic vs. collaboration logic.

Gather the DORA metrics

It’s also important to gather the DORA metrics including lead time and deployment frequency.

Take the DORA DevOps Quick Check

The DORA DevOps Quick Check is a simple five question assessment of how well you are delivering software.

Improve your DORA metrics

If you are using microservices but your lead time is high and your deployment frequency is low, then that’s a sign that something is wrong. Perhaps, software delivery is slowed down by the architectural smells I described earlier. Or perhaps, there are problems with your process, such as not using DevOps as defined by the Devops handbook. Or with your organization, such as having silo’d teams rather than a set of loosely coupled teams as described by Team Topologies. The DORA website hassome followup assessments that can help you identify what needs to be improved.

Summary

  • One of the main goals of microservices is to accelerate development
  • But achieving that goal requires a well-designed architecture. In particular, you must avoid:
    • Tight design-time coupled services - otherwise, you will be constantly coordinating with other teams
    • An excessively fine-grained architecture - otherwise, you will spend too much time on collaboration logic
  • Determine whether microservices are helping or hindering development by surveying the developers and gathering the DORA metrics

anti-patterns   architecture   microservice architecture   developer experience  


Copyright © 2024 Chris Richardson • All rights reserved • Supported by Kong.

About Microservices.io

Microservices.io is brought to you by Chris Richardson. Experienced software architect, author of POJOs in Action, the creator of the original CloudFoundry.com, and the author of Microservices patterns.

ASK CHRIS

?

Got a question about microservices?

Fill in this form. If I can, I'll write a blog post that answers your question.

NEED HELP?

I help organizations improve agility and competitiveness through better software architecture.

Learn more about my consulting engagements, and training workshops.

LEARN about microservices

Chris offers numerous other resources for learning the microservice architecture.

Get the book: Microservices Patterns

Read Chris Richardson's book:

Example microservices applications

Want to see an example? Check out Chris Richardson's example applications. See code

Virtual bootcamp: Distributed data patterns in a microservice architecture

My virtual bootcamp, distributed data patterns in a microservice architecture, is now open for enrollment!

It covers the key distributed data management patterns including Saga, API Composition, and CQRS.

It consists of video lectures, code labs, and a weekly ask-me-anything video conference repeated in multiple timezones.

The regular price is $395/person but use coupon NPXJKULI to sign up for $95 (valid until December 25th, 2024). There are deeper discounts for buying multiple seats.

Learn more

Learn how to create a service template and microservice chassis

Take a look at my Manning LiveProject that teaches you how to develop a service template and microservice chassis.

Signup for the newsletter


BUILD microservices

Ready to start using the microservice architecture?

Consulting services

Engage Chris to create a microservices adoption roadmap and help you define your microservice architecture,


The Eventuate platform

Use the Eventuate.io platform to tackle distributed data management challenges in your microservices architecture.

Eventuate is Chris's latest startup. It makes it easy to use the Saga pattern to manage transactions and the CQRS pattern to implement queries.


Join the microservices google group