Distributed Monolith
Tight coupling over the network — distribution’s latency without microservice independence.
You’ve split the deployables. Congratulations — maybe.
If two “microservices” still need a flood of information from each other to do basic work, you didn’t get microservices. You got a distributed monolith: tight coupling, plus DNS, cache, network latency, and security hops on every conversation.
Guard against that whether you used DDD or some other cut. The label on the box doesn’t save you.
The three checks
When you’re validating a split (especially after bounded contexts):
- A small amount of duplication is allowed
- There should be no hard dependency that forces services to move as one
- Communication overhead should stay minimal
Duplication example: notification keeps a user id (and maybe a display name) so it can say “X sent a message to Y” without calling user service on every ping. That’s intentional duplication for independence — not “copy the whole user table everywhere.”
If notification still depends on user service for almost everything, merge them — or you’ve chosen to keep a distributed monolith on purpose.
Amazon Prime — audio and video
A clear example: Amazon Prime used to run separate services for audio and video.
When you’re watching a movie, you need both. You’re not consuming audio alone or video alone the way you might with music. The two services talked constantly. That communication overhead got expensive.
They merged audio and video into one service and reportedly saw a huge efficiency jump — on the order of ~90% in that story. Less cross-service chatter means less DNS/cache/network/security tax on the hot path, and less CPU spent on glue instead of the actual work.
Audio needs Video data…
Tight coupling + network = distributed monolith.Distributed monolith Healthier boundary
[Audio svc] ←──heavy──→ [Video] [Media service]
│ │ │
movie path needs both audio+video together
latency stacks one hop for the use case
Tight coupling + network = distributed monolith. Independence of services — and understanding of the domain — is what keeps a real microservice design efficient. There’s no magic tool that does that for you.
When not to panic
Not every cross-service call is a distributed monolith. A rare lookup or an async event is normal. The smell is constant synchronous need for the other service to complete the core use case.
Also: merging isn’t failure. Sometimes the honest microservice count goes down after production teaches you which walls were fake.
Production pitfall
Fixing latency with more caching between two chatty services instead of questioning the split. You hide the symptom, keep the coupling, and now you also have cache invalidation bugs. If the use case always needs both, put them in one service (or one bounded context) and spend your distribution budget where independence is real.