The microservices pattern has attracted a collection of recurring mistakes. These anti-patterns cause the systems that implement them significant operational and development problems.

The distributed monolith

The distributed monolith is the worst outcome of a microservices migration: services that must be deployed together because they share a database, share a domain model via a shared library, or have synchronous dependencies that make independent deployment impossible. The system has all the operational overhead of distributed services without the deployment independence that justifies that overhead. The diagnosis: if deploying service A requires deploying service B, they are not independent microservices.

Chatty services

Microservices that make synchronous calls to many downstream services per request, service A calls B, which calls C, D, and E, create latency chains, tight coupling, and cascading failure paths. The diagnosis: a single user request triggers 15 service-to-service calls. The remediation: use asynchronous patterns where synchronous responses are not required, aggregate calls in a BFF or API gateway, and question whether the service decomposition reflects the domain boundaries correctly.

Shared databases

Multiple services that read and write to the same database table are not microservices, they are a shared database anti-pattern. Any change to the shared schema requires coordinating all dependent services. The services cannot deploy independently because their data contracts are coupled. The database is a hidden dependency that defeats the loose coupling microservices are supposed to provide.

Premature decomposition

Decomposing a system into microservices before the domain is well understood produces service boundaries that are wrong. The symptom: every new feature requires changes to multiple services because the boundaries do not align with the actual change patterns. The fix is more painful than the original monolith: merging services requires state migration and deployment coordination. The lesson: microservices boundaries should reflect stable domain boundaries, not organisational structure or personal preference.