The problem
A large monolith owned by many teams turns into a queue: every release needs coordination, one hot path forces the whole app to scale, and a single bad deploy takes everything down.
How it works
Core characteristics:
- Organised around business capabilities, not technical layers.
- Database per service. No other service reads your tables.
- Independent deploys. A service can ship without coordinating with others.
- Smart endpoints, dumb pipes. Logic lives in services, not in the bus.
- Designed for failure with timeouts, retries, circuit breakers and idempotency.
Communication choices
| Style | When |
|---|---|
| Sync REST/gRPC | A query needs an immediate answer |
| Async events | State changes other services react to (e.g. EntryPublished) |
| Async commands via a queue | Long-running work (bulk publish, exports) |
- Many teams need independent release cadences
- Parts of the system have very different scale or reliability needs
- Domain boundaries are well understood
- A small team or a new product whose boundaries are still moving
- No investment in CI/CD, observability and platform tooling
- Services would share one database anyway
Trade-offs
- ✅ Team autonomy, independent scaling, fault isolation, freedom of technology.
- ❌ Distributed-systems complexity: partial failure, eventual consistency, versioning.
- ❌ Operational load. Every service needs a pipeline, dashboards, alerts and on-call.
- ❌ Cross-service queries and transactions get hard. You need sagas, CQRS and API composition.
Contentstack's platform runs as 60+ services on Kubernetes. The flip side showed up in developer experience: setting up a local environment meant cloning and configuring dozens of repos plus MongoDB and Redis. Our team built a Claude-driven setup agent that provisions and validates the whole local stack. Microservices shift cost onto platform tooling, and you have to pay it.
In one line
Microservices trade code complexity for operational complexity. I'd pick them for organisational scaling and uneven load, never just for "clean code", and only with CI/CD, tracing and contract testing in place.
Cheatsheet
The whole topic on one page. Click to open full screen.
Sources & further learning
Videos, courses, docs and books I recommend for this topic.
Related topics
Modular Monolith
One deployable unit, internally split into strongly bounded modules with explicit public APIs — microservice-style boundaries without the distributed-systems tax.
API Gateway & Backend-for-Frontend (BFF)
A single entry point that handles cross-cutting concerns (auth, rate limits, routing); BFFs go further with one tailored backend per client type.
Saga Pattern
Keep data consistent across services without distributed transactions — a sequence of local transactions, each with a compensating action if a later step fails.
Event-Driven Architecture
Services announce facts ("EntryPublished") and others react asynchronously — decoupling producers from consumers in time, space and knowledge.
Sidecar & Service Mesh
Move networking concerns — mTLS, retries, traffic splitting, telemetry — out of application code into a proxy deployed next to every service.