Split functionality into independently deployable services around business domains.
If you are new here: Microservices architecture is the approach of building a system as a collection of small, independently deployable services — each owned by one team, responsible for one business domain, backed by its own database. Instead of one large monolith that does everything, you have an Orders service, an Inventory service, a Payments service, and so on. Each service can be deployed independently, scaled independently, and written in the language that best fits its job. The gains are real: team autonomy, granular scaling, fault isolation. So are the costs: distributed system complexity, network calls between services, and significant operational overhead. Microservices are not always better — they're a trade-off that pays off at a specific team and traffic scale.
| Term | Plain meaning |
|---|---|
| Microservice | A small, independently deployable service responsible for one business capability |
| Bounded context | A DDD concept: the explicit boundary within which a domain model is defined and consistent |
| Service mesh | Infrastructure layer handling service-to-service networking (mTLS, retries, tracing) |
| API Gateway | Entry point that routes client requests to the right downstream microservice |
| Polyglot persistence | Each service uses the database technology best suited for its data (Postgres, Redis, Cassandra) |
| Polyglot programming | Each service can use the programming language best suited for its workload |
| Distributed tracing | Tracking a request as it flows through multiple services (Jaeger, Zipkin, Datadog) |
| Circuit breaker | A pattern that stops calling a downstream service that's repeatedly failing |
| Conway's Law | Systems tend to mirror the communication structure of the teams that build them |
As a monolith grows, two things break down: team coordination and deployment velocity.
Team coordination: 50 engineers all working in the same codebase. Every merge conflicts with someone else. Every test run takes 45 minutes because it runs tests for every team's code. Every deployment requires all teams to coordinate. Teams are constantly blocked on each other. A bug in the Payments module needs the Payments team to wait for the Inventory team's release to go out first.
Deployment velocity: at Netflix scale, they need to deploy hundreds of times per day. With a monolith, each deployment is a full rebuild and test cycle. You can't ship a bug fix in 10 minutes — you have to wait for the next scheduled deployment window.
Microservices solve this by drawing hard boundaries between teams. The Payments team owns the Payments service. They deploy it whenever they want. Their deployments don't require sign-off from the Inventory team. The Payments service's tests run in 3 minutes (only testing Payments code). They ship 10 times a day if they want to.
In plain terms: microservices are primarily an organizational tool — they give teams the independence to move at their own speed. The technical benefits (scaling, fault isolation) are real but secondary.
Analogy: A city versus a single giant building. A city has independent buildings — a hospital, a school, shops. If the school floods, the hospital still operates. You can renovate the school without moving out of the hospital. The trade-off: the city needs infrastructure (roads, utilities, zoning) that a single building doesn't. Microservices are the city model: more overhead, but each piece is independent.
The single most valuable property of microservices is independent deployment. Each service has its own:
This means a team can ship a fix in 15 minutes: push code, CI builds and tests in 3 minutes, deployment pipeline ships in 5 minutes, done. No waiting for other teams. No global deployment freeze windows.
In plain terms: independent deployment is what "team autonomy" actually means in practice. If your monolith deploys once a week because coordinating all teams takes that long, you're shipping 52 times per year. Netflix ships thousands of times per day per service — the compounded advantage over years is enormous.
Tiny example: a bug is found in the Payments service at 2pm on a Friday. The Payments team:
10 minutes from discovery to production fix, with no impact on the Orders or Inventory teams. In a monolith, this fix would wait until Monday's deployment window or require a risky emergency deployment of the entire application.
When Orders needs to check inventory, it can no longer call inventory.checkStock(itemId). It must make a network call: GET https://inventory-service/api/v1/stock/item-5512.
This network call adds latency, introduces failure modes, and requires contract management:
Latency: even a local call takes 1–5ms. A checkout flow that makes 5 sequential service calls adds 5–25ms of pure network overhead, plus service processing time.
Failure modes: the network can time out, the downstream service can crash, DNS can be slow. Every service-to-service call is a new category of failure that didn't exist in the monolith.
API contracts: services must maintain stable APIs. If Orders calls Inventory's /stock/{id} endpoint and Inventory changes its response schema, Orders breaks. You now need API versioning, contract testing, and backward compatibility management.
In plain terms: every function call you convert to a network call adds a whole new failure mode and latency budget. You must design for it explicitly.
Concrete sketch: Amazon checkout: to display one checkout page, the frontend calls the API gateway, which calls Orders, Cart, Inventory, Pricing, Recommendations, Shipping, and User Profile services. That's 7 network calls, potentially 30–100ms of latency per call if not parallelized. Amazon invests heavily in parallel calls, local caches, and circuit breakers to keep this fast.
In a monolith, a memory leak or infinite loop in one module can take down the entire application. In microservices, that same bug only crashes the service it's in. Other services continue serving traffic.
When the Inventory service is down:
The key is designing for partial failure. Services must not blindly assume their dependencies are available. They need circuit breakers, fallback responses, and graceful degradation.
In plain terms: in microservices, failures are contained to the service that broke. The blast radius is smaller. But this only holds if you design for it — if every service has a circuit breaker and fallback, not if they just crash and wait for recovery.
Concrete sketch: Netflix Chaos Monkey is a tool that randomly kills services in production. Netflix uses it specifically because microservices should survive individual service failures. If Chaos Monkey kills the Recommendations service, Netflix should still stream video — recommendations just show cached results or defaults. Testing this in production is how Netflix verifies their fault tolerance.
The industry has overcorrected. Microservices became fashionable, and many teams adopted them before they were ready, creating distributed systems nightmares:
The Bezos mandate (Amazon 2002): Jeff Bezos mandated that all teams must expose their data through service APIs. But Amazon spent years building the infrastructure before that mandate was achievable. They built the deployment tools, monitoring, and API gateway first.
| Property | Microservices | Monolith |
|---|---|---|
| Team autonomy | High — independent deployments | Low — shared codebase and deployments |
| Scaling granularity | Fine — scale individual services | Coarse — scale the whole app |
| Fault isolation | High — blast radius limited to one service | Low — one bug can crash everything |
| Operational overhead | High — N services to deploy, monitor, debug | Low — one thing to run |
| Distributed tracing | Required — cross-service request tracking | Not needed |
| Transaction complexity | High — no shared ACID transactions | Low — one DB |
| Right team size | 20+ engineers with DevOps maturity | 1–20 engineers |
The microservices vs monolith debate is one of the most contentious in software engineering — and both sides have real points. The key insight: microservices are an organizational solution, not a technical one. They exist to give teams independence. If your team doesn't have the coordination problems microservices solve, you're paying the distributed systems costs without getting the organizational benefits. Before breaking up a monolith, ask: "Is our velocity limited by deploy coordination?" If yes, microservices help. If your team can deploy the monolith independently already, microservices will only add complexity.
Next: Serverless Architecture — what if you removed the concept of "services" entirely and just deployed functions?
Microservices — each business domain is an independent service with its own database and deployment lifecycle.