A man sitting in front of a laptop computer.

Anti-patterns in Microservices (Don’t Do These)

Microservices are a popular approach to software architecture that aim to break up monolithic code into maintainable chunks. These discrete chunks allow for continuous delivery of a service while developing on top of what is in production.

That flexibility is exciting in an agile environment, but rushing into deploying your code as a suite of microservices can put you at risk of incorporating anti-patterns that may cause significant problems down the line. 

Watch out for these four common pitfalls as you start building your own microservices. 

1: Not Just Your Code 

A common anti-pattern in microservices is thinking that microservices deal with just code and nothing else. This anti-pattern might crop up when the microservice inherits code from a larger project but has now been spun off into its own project.   

But a microservice is not just code. It is an entirely self-contained system where the container holds everything the service needs. You’ll need each microservice, for example, to have its own datastore

Why? If your microservices have separate code but all interact with the same datastore, a major change to the datastore could force rewrites across your entire codebase. Exactly the problem you were trying to avoid with a microservices architecture.  

This doesn’t mean you need an entire database management platform for each and every microservice. You do need to consider approaches that manage this problem. Datastores built for scaling rapidly (NoSQL databases like MongoDB), caching strategies (to retrieve data quickly using a service like Redis), or a well-defined API gateway to a larger service are all ways to avoid the monolithic datastore anti-pattern. 

2: Avoiding the Monolith

Having one giant datastore for multiple microservices is a symptom of this next anti-pattern. When microservices share resources, you end up with a monolithic app—just spread across multiple repositories. This means your architecture is not diversified and your microservice containers are interdependent.  

A tangled web of microservices that call and rely on one another can make your overall application brittle, especially if you are not precise about the way the microservices communicate with one another and the order in which they operate. This can lead to code changes in one microservice affecting others, and increased effort to disentangle the services that were meant to be independent.

This talk by Holger Reinhardt provides helpful guidance on thinking through your overall microservice architecture to avoid the monolith.

3: Versioning, or Lack Thereof

Neglecting to implement a good versioning strategy for your microservices is another classic anti-pattern. Versioning is key to maintaining continuous deployment while iterating on your services. There are several approaches to versioning a microservice, but the important thing is to make sure you have a solid strategy that can handle changes across your microservices as new functionality is added. 

4: Too Much at Once 

Many anti-patterns stem from this larger one: trying to turn everything into a microservice all at once. Once you learn about the benefits of microservices, it’s tempting to want to implement them immediately by smashing your monolithic app into dozens of tiny microservices. 

The risk of this anti-pattern isn’t the microservices themselves, but that your development processes might not yet be well enough defined. If you create a dozen microservices, for example, but later discover an issue when testing what happens when there is a network failure, then you’ve multiplied your work to fix the issue.

You can avoid numerous code rewrites by thoroughly building out your first microservice, top to bottom, before adding others. Focus on the quality of your microservices over the quantity, and you will save time and effort down the line. Navy SEALs say, “Slow is smooth, and smooth is fast.†Taking time to get things right saves you time in the long run. 

Microservices are a great way to write and deploy code for customers who demand uninterrupted access. Avoid these anti-patterns, and you’ll save yourself from some common microservices pitfalls.