Skip to content

Microservice architecture

Pattern · Chapter 8

  • The microservice architecture (MSA) builds applications from small, autonomous, independently versioned, self-contained services.
  • Services expose well-defined interfaces and talk over standard, lightweight protocols. Each service is a black box — implementation and complexity hidden from consumers.
  • Each service does one thing well; services collaborate to accomplish larger tasks. Well-suited to large / complex systems by decomposing them into manageable pieces.
  • An API gateway is the usual entry point: an HTTP server that routes client requests to the right microservice.
  • MSA emerged from the shortcomings of traditional service-oriented architecture (SOA) and the monolith — sometimes called “SOA done right”.
  • SOA benefits remain (business/technology alignment, federation, vendor diversity, interoperability), but SOA can be expensive and overkill.
  • Key difference: rather than an enterprise service bus (ESB), MSA pushes ESB-like functionality into the services themselves.
CharacteristicWhat it means
Small, focused servicesUnix-philosophy scope; each owns one business capability
Well-defined interfacesBlack boxes with clear entry/exit points
Autonomous & independently deployableLoosely coupled; deployed on their own
Independent data storageEach service owns its data
Lightweight protocolsREST/JSON, AMQP, gRPC — sync or async
Better fault isolationOne service failing doesn’t down the whole system
  • Small, focused services → easier to understand and modify, faster to develop, quick IDE loading, faster onboarding; each service can be owned by a single small team working in parallel. Pairs naturally with bounded contexts from domain-driven design.
  • Autonomous & independently deployable → services evolve independently as long as the interface is stable; enables continuous deployment and organizational agility.
  • Better fault isolation → contrasts sharply with the monolith, where one fault can bring down everything (see Availability).
  • No mandated protocol; can be synchronous or asynchronous — driven by requirements.
  • REST + JSON — common choice for synchronous calls (HTTP endpoints).
  • AMQP — open standard for asynchronous messaging across platforms/orgs; delivery guarantees: at least once, at most once, exactly once.
  • gRPC — Google’s high-performance alternative; built on protocol buffers (language/platform-neutral serialization) and HTTP/2 (lower latency, higher compression); popular with containers and polyglot services.
  • MSA lets you use multiple languages, runtimes, frameworks, and data stores — pick best-of-breed per problem.
  • Polyglot programming — different services in the language best suited to their task.
  • Polyglot persistence — each service owns its data store and picks the best DB (e.g. graph DB for recommendations, document DB for a read-heavy catalog, RDBMS for transactional orders).
  • Caution — too many technologies: mastery is costly; more training, more complex build/deploy/test, and a diverse team needed to maintain it. Justify each new technology.
  • Goal: fine-grained services, each a single business capability; smaller scope → higher reusability.
  • Nanoservices (anti-pattern) — services too fine-grained. Symptoms: more services → more network chatter and overhead (config, registry entries), reduced performance, and fragmented logic. When a service’s overhead outweighs its utility, refactor it — combine nanoservices or fold their logic into an existing service. Use judgment; occasional standalone nanoservices are fine.
  • Avoid sharing dependencies (frameworks, third-party libs) between services — preserves independence, avoids widening test/defect scope, and prevents host affinity.
  • Stateless vs stateful — prefer stateless; when state is needed, persist it externally (RDBMS, NoSQL, cloud storage) for availability, reliability, scalability, and consistency.
  • In the cloud, the number and location of service instances change dynamically, so static config isn’t enough. A service registry (a highly-available, up-to-date DB of instances and locations) tracks them.
  • Self-registration — instances register/deregister themselves and send heartbeats; simple but couples instances to the registry and needs logic per language/framework.
  • Third-party registration — a dedicated service registrar registers, deregisters, and health-checks instances; decouples services from the registry, but is another component to run.
  • Client-side discovery — the client queries the registry and load-balances across returned instances; simple but couples client to registry and needs per-language logic.
  • Server-side discovery — the client hits a router/load balancer that queries the registry and forwards the request; decouples clients and simplifies their code, but adds a component to manage and extra network hops.
  • MSA is a distributed system — inherent complexity the monolith avoids; harder to trace what/where failed.
  • Decomposition is an art requiring domain knowledge — too fine → too many services to manage; too coarse / tightly coupled → a “monolith in disguise” that must deploy together.
  • Multiple databases complicate transactions spanning services — often needs event-sourcing and eventual consistency, itself added complexity.
  • Benefits must outweigh the added complexity — not the right fit for every application.
  • Software Architect’s Handbook (Packt, 2018), Ch.8 “Microservice architecture”, pp. 607-637.