I've been programming for 15 years, and I've worked in enough different environments with microservices.
A bunch of people wrote a bunch of code, and now they're sad about it.
- Just too much to know, it's nearly impossible to know the whole system.
- Everything's tangled up, there's unrelated wires everywhere because "I need to do an `if` over there", nobody knows where their part of the system ends and others' begin. Even worse, some improvident enterprising soul started using shared mutable state in memory.
- Everyone wants to get in on releases, you're taking very unrelated changes to prod at the same time, there's a lot of waiting for gigantic test suites to pass, a whole new 500MB Docker image needs to go out all servers when you only changed a few bytes, etc.
- Your frontpage is being hammered, you can't bill clients anymore.
- Somebody misconfigures something about taxes, you can't show your homepage anymore.
Microservices help with some things, and get in the way with others.
It's also about feasability, but that doesn't apply to software.
+ You now have different parts of the application with their own databases, web workers, background workers, etc. You can scale precisely to what the customers need from you right now!
- Distributed systems aren't to be taken lightly. They're their own specialization inside backend. If you don't take it seriously, different parts of your system believe in different truths.
- Your store service doesn't work because the inventory service doesn't work.
+ If you have a scheduling problem, you can use Prolog! If you have a CPU-heavy problem, you can use Rust!
- You're now on call for your microservices. If someone downstream from you is having problems, you now need their help or learn their system. Your dependency tree can be arbitrarily deep.
+ Nobody will feel tempted to pass unrelated information through your code. You control how much impact observability has in your performance.
- Removing a field from an API takes many quarters. Once you start emitting a stream of events in a certain schema, you're potentially locked to it forever.
The reverse is also true: if you want to contribute a change to somebody else's code, you need to learn their customs first.
+ Only one concern, scope creeps start smelling pretty fast.
- Different systems will have different assurances.
- When people can't convince someone to add a feature to some sevice, they might very well fork it and implement that thing in the new fork.
- Eventually, you'll have to adopt governance to decide when to sunset them.
- The problem was "other people" and "code". It's still that.
- It's going from living in a loft to living in a campus.
- Much more tech involved. Don't pay for it unless you're also reaping tech benefits.
- Nobody wants to becomes an expert on distsys, DBs, k8s, and everything.
- You start concentrating competency (both tech and domain) on teams.
- You can outsource to both services and consultancy.
- Microservices shifts the focus to teams and their stewardship.
- It's going from living in a loft to living in an apartment.
- Your store can DoS your homepage.
+ No more timeouts, retries, sagas, or eventual consisteny.
You can still import alien code through JNI, FFI, dynamic libraries, etc. But
you're now constrained to your ecosystem. Like Erlang? Too bad! JNI takes a
bunch of time on the first run? Too bad! Need to translate the in-memory
representation at the boundary? Too bad!
This essentially means there's only a single "language plarform" team.
- It's easier to forgive a dumb argument in a function call than in an HTTP call.
- It's also easier to undo.
In microservices, this was being enforced by other teams.