How To Fail at Micro-Services
Tags: microservices, backend, node, devops
Published: 2023-08-19 11:33:49

---
title: How To Fail at Micro-Services
published: true
date: 2023-08-18 17:18:25 UTC
tags: microservices, backend, nodejs, devops
canonical_url: https://blog.scalablebackend.com/how-to-fail-at-micro-services
---

![Wrong way](https://dev-to-uploads.s3.amazonaws.com/uploads/articles/g8zonhtxdewb624a35da.jpg)

Doing micro-services the wrong way can be a death sentence for your project. If your architecture resonates with some elements of todays list, it might be a good time to stop what youre doing and reflect on it.

First, we need to define the basic properties of micro-services. Amazing resources like [Building Microservices](https://samnewman.io/books/building_microservices_2nd_edition/) and [Microservice Architecture](https://www.oreilly.com/library/view/microservice-architecture/9781491956328/) tell us they are supposed to be:

- Small in size

- Messaging enabled

- Bounded by contexts

- Autonomously developed

- Independently deployable

- Decentralized

- Built and released with automated processes

- Loosely coupled

- Focused on one thing

If you built your back-end with micro-services in mind, but dont respect some of those properties, its an obvious sign you made a mistake.

But sometimes, wrong architecture choices sneak up on you. You end up with something close to micro-services but dont respect some of their rules.

## Distributed monolith

The most common is to build a distributed monolith instead of micro-services. This is a complete subject in itself, I highly recommend you read more about it.

{% embed https://blog.scalablebackend.com/understand-the-difference-between-monolith-microservices-and-distributed-monolith %}

## Shared database

Lets get this straight: its impossible to create independent and loosely coupled services with a shared database.

You will quickly realize how shared ownership of a database is a nightmare and has a negative impact on development and maintenance. It doesnt integrate too well with ORMs, and Im not even talking about deployment.

Yes, in a monolith you can have a single database, which makes things easy. With micro-services, you dont have a choice but to make it more complex by separating databases for each service.

Its one of the trade-offs with micro-services, its an added complexity that allows you to take advantage of micro-services.

## Lack of automation

Micro-services definitely require more effort to develop, deploy, and maintain. Thats why one of the cornerstones of your system should be automation.

I guess you could try to create a few micro-services without automation, but on a real project thats simply unrealistic. Mainly, testing and deployment quickly become impossible without a completely automated CI/CD system.

## Shared business logic

Sharing business logic goes against the properties expected from micro-services, as it makes your services highly coupled.

And, in practice, you will also realize it has fewer benefits than expected. Using a shared package for business logic forces you to update the package itself, before updating your services.

It makes development longer and causes context-switching for developers, without bringing any real value.

## Starting with micro-services

In recent times, micro-services became trendy. While they solve several specific challenges, theyre not a silver bullet.

In practice, they should only be used when you already have a monolith, but have challenges micro-services solve.

Lets say you started your back-end application, day one, as micro-services. There is a higher probability you did so because you wanted to use micro-services than to solve a real challenge.

## Lack of tests

Micro-services should be tested as much, if not more, compared to a monolith.

They should be tested in isolation, but thats not all. If your services communicate (usually through events), it means they agree on a contract (implicitly or explicitly).

This contract should definitely be a part of the scope of your tests.

## Not independently deployable

If, for some reason, you are unable to deploy a new version of a service in autonomy, its an obvious sign your services are highly coupled.

You shouldnt need the other services at any point in the development and deployment process of a service. In [Hands-on Microservices with Kotlin](https://www.oreilly.com/library/view/hands-on-microservices-with/9781788471459/), we learn:

> Having the ability to deliver constantly is one of the advantages of the microservices architecture; any constraints should be removed, as much as we remove bugs from our applications.
> 
> We should take care of deployments from the beginning of the design of our microservices and architecture; finding a constraint on this area at late stages could have a big impact on the overall application.

## Synchronous communication between services

Using synchronous (request-response) communication between services breaks the independent & loosely coupled properties.

If you use synchronous communication between services, you are actually building a distributed monolith. After reading about distributed monolith, you should know its the exact opposite of what we want.

It doesnt bring the added value of micro-services but also loses the simplicity that comes with a monolith.

Moreover, with micro-services, we need to guarantee messages get delivered. With request-response communication, when a process extends to more than one service, its simply impossible.

## Need for other services to work

Maybe the **most important** , but still the most often **ignored**.

One of the downsides of synchronous communication between services is the need for multiple services to work at the same time.

In theory, one service should be able to work perfectly fine even if all other services are down. Obviously, the system itself wont work as expected, but services in isolation should.

This is generally made possible by:

- Limiting relationships between services

- Using deduplication

- Communicating through events.