How Microservices Work

Intermediate
9 min read· Architecture & Design

Microservices is an architectural style where a system is built as a collection of small, independently deployable services — each owning its own data, running in its own process, and communicating over a network. Each service does one thing well: User Service, Order Service, Payment Service. Teams can deploy services independently, choose their own tech stacks, and scale each service separately. The trade-off: distributed systems are fundamentally harder to build, test, and operate than monoliths.

Think of it like a city vs a self-contained island

A monolith is a self-sufficient island: everything is in one place, communication is instant (a function call), and it's simple to understand. But the whole island must be rebuilt and redeployed as one unit. A microservices city has many specialised districts — financial, commercial, residential — each operating independently, connected by roads (APIs). Districts can be expanded or renovated independently. But now you need city planning (service discovery), traffic management (load balancers), and coordination between districts (distributed transactions).

Step by Step

1 / 6

Key Concepts

Bounded Context

A DDD (Domain-Driven Design) concept: a clearly defined boundary within which a domain model applies. "Order" means something different in the Order Service (items, total, status) vs the Shipping Service (destination, dimensions, tracking). Each service owns its model within its bounded context — no shared domain objects across service boundaries.

Database Per Service

Each microservice owns its own database and no other service can query it directly. Service A must call Service B's API to get B's data — never hitting B's database directly. This enforces loose coupling: B can change its schema without coordinating with A. The trade-off: joins across services are impossible; you must denormalise data or use the Saga pattern for distributed transactions.

Saga Pattern

A pattern for distributed transactions across services. Instead of a single ACID transaction (impossible across databases), a saga is a sequence of local transactions, each publishing an event that triggers the next. If a step fails, compensating transactions undo previous steps. Choreography sagas use events; orchestration sagas use a central coordinator. More complex than local transactions.

API Gateway

A single entry point for all client requests. Handles cross-cutting concerns: authentication, authorisation, rate limiting, SSL termination, routing, and response aggregation. Decouples clients from internal service topology — clients call /api/orders, the gateway routes to whichever service handles orders. Backends can be refactored without changing client code.

Circuit Breaker

A proxy around remote calls that monitors failure rates. States: Closed (calls flow normally), Open (failing fast — no calls made to the unhealthy service, fallback returned immediately), Half-Open (allow a test call to check if the service has recovered). Prevents one slow/failed service from causing a cascading failure across the entire system.

Event-Driven Architecture

Services communicate by publishing domain events rather than direct API calls. When an order is placed, Order Service publishes an "OrderPlaced" event to Kafka. Inventory Service, Email Service, and Analytics Service all consume the event independently. Services are fully decoupled: Order Service doesn't know who consumes its events.

gRPC

Google's open-source RPC framework. Uses Protocol Buffers (binary serialisation) instead of JSON, HTTP/2 instead of HTTP/1.1. Typically 5–7x faster than REST/JSON for internal service communication. Strongly typed (schema defined in .proto files), auto-generated clients in 10+ languages. Preferred for high-throughput internal service calls.

Bulkhead Pattern

Isolate resources between services so one overloaded service can't exhaust shared resources (thread pools, connection pools) and take down others. Named after bulkheads in ships — compartments that prevent one leak from sinking the whole vessel. Implemented by giving each downstream service its own thread pool/connection pool.

Key Facts

  • Amazon was one of the earliest adopters of microservices — Jeff Bezos's "API Mandate" (2002) required all teams to expose their data and functionality only through service APIs. This became the foundation of AWS.
  • Netflix runs over 700 microservices. Their public chaos engineering tool, Chaos Monkey, randomly terminates services in production to ensure systems are resilient to individual failures.
  • Martin Fowler coined the "Microservices" term in a 2014 article, but the concept — small, independently deployable services — had been practiced at companies like Amazon for over a decade.
  • The "Microservices Premium" is real: studies show microservices architectures require significantly more operational complexity. Many startups should start with a well-structured monolith and extract services only when a specific scalability or team autonomy need emerges.
  • Sam Newman's book "Building Microservices" (2015) is the canonical reference. The most common advice: don't start with microservices. Start with a modular monolith, identify seams where services should split based on actual team and scale needs, then extract.
  • Service mesh tools (Istio, Linkerd) handle cross-cutting concerns (mTLS, retries, circuit breaking, tracing) at the infrastructure level via sidecar proxies — so application code doesn't need to implement them.

Real-World Applications

Independent deployment pipelines

The core microservices benefit: the Payments team ships 5 times per day without waiting for the Recommendations team. Each service has its own CI/CD pipeline, test suite, and deploy process. A bug in the Search Service doesn't block a critical Payments hotfix. At monolith scale, this independence is impossible.

Technology polyglot

The ML recommendation service is Python (best ML libraries). The low-latency bidding service is Go (best performance). The admin dashboard backend is Ruby on Rails (fastest to build). The real-time notifications service is Node.js (event-driven). Each team picks the best tool for their job — a monolith enforces one language for everything.

Independent scaling

During Black Friday, the Product Catalogue Service needs 500 instances; the User Registration Service needs 5. In a monolith, you scale everything together. With microservices, you scale only the services under load — significantly reducing infrastructure costs during uneven traffic spikes.

The strangler fig pattern

Migrating from a monolith to microservices incrementally. New features are built as separate services. Existing monolith functionality is extracted piece by piece — the new service routes around the old code like a strangler fig vine grows around a tree. The monolith shrinks over time until it can be decommissioned. Avoid the "big bang" rewrite.

Frequently Asked Questions

Should I start a new project with microservices?

Almost certainly not. Microservices solve problems of scale and team autonomy that small projects don't have. The overhead — service discovery, distributed tracing, network latency, distributed transactions, operational complexity — is enormous. Start with a well-structured modular monolith. Extract services when you have clear signals: a specific team needs independent deployment, a specific component needs different scaling, or a specific component needs a different technology stack.

How do you handle transactions across microservices?

You don't get ACID transactions across services. Options: (1) Saga pattern — sequence of local transactions with compensating rollbacks on failure. (2) Eventual consistency — accept that data will be consistent "eventually" rather than immediately. (3) Re-think your service boundaries — if you need frequent cross-service transactions, your services are probably too small (the "distributed monolith" anti-pattern). Two-Phase Commit (2PC) exists but is an operational nightmare in distributed systems.

What is the difference between microservices and SOA?

SOA (Service-Oriented Architecture, 2000s) is the predecessor. Both decompose systems into services. Differences: SOA used heavyweight protocols (SOAP, XML, ESB enterprise service buses). Microservices use lightweight protocols (REST, gRPC, message queues). SOA services were larger and shared databases. Microservices are smaller, each with their own database. Microservices emerged partly as a reaction to the complexity of ESBs.

What is a service mesh?

A service mesh (Istio, Linkerd, Consul Connect) adds a sidecar proxy next to every service instance. The proxy intercepts all network traffic to and from the service. The mesh layer provides: mTLS (mutual TLS for service-to-service auth), retries, circuit breaking, rate limiting, and distributed tracing — without application code changes. The "data plane" (proxies) handles traffic; the "control plane" configures them. Large Kubernetes deployments use service meshes to avoid implementing these concerns in every service.

Related Topics