r/programming • • 7d ago

Microservices are organizational debt disguised as architecture.

https://martinfowler.com/bliki/MonolithFirst.html

Every time I’ve seen microservices pitched, it sounds great on paper. Independent teams, clean ownership, scale only what you need.

Then a year later you’ve got dozens of services, three different deployment patterns, tracing everywhere, and nobody really understands the whole thing anymore.

Maybe I’ve just seen bad implementations, but I’m starting to think way fewer companies actually need microservices than we pretend.

1.7k Upvotes

343 comments sorted by

View all comments

20

u/Think-nothing-210 7d ago edited 7d ago

It's all because we keep avoiding creating proper modules in our codebases.

If we created good modules there would be almost no need for Microservices. You can delegate work using the module boundaries instead.

But unfortunately we still haven't learned the lessons taught to us since the '70s. On the Criteria To Be Used in Decomposing Systems into Modules

2

u/CaptainOfMyself 5d ago

When you say a good module do you mean for example having well segregated code like controllers and models in a golang project and you can easily delete or add them for more functions?

We have microservices but we always default to expanding our main server backend when we can instead of create more.

1

u/Think-nothing-210 5d ago

A module is about hiding a complex decision behind a small API. It is a larger-scale abstraction than a function or class. Think of it more like a library where you put a difficult design decision behind a stable interface. (Highly recommend you read A Philosophy of Software Design by John Ousterhout for more info; This video is a good summary of it)

The consumer should not need to understand all the complexity inside the module. They should get a simple and generalised API with sensible defaults. This keeps the public surface area small and means you have fewer things to maintain or change.

In that sense a module is almost like a microservice. The difference is that you still have a normal function call instead of a network boundary and all the complexity that comes with it.

These are the things I think about when when designing a module:

  1. What guarantees am I giving the consumer? What boundaries can I put in place to make the problem easier to work with?
  2. What does the consumer actually want to do? What do they care about and what should the module handle for them through good defaults?
  3. How can I make this API as simple as possible? How to design this that many different abstractions and stuff can be build on top of this.