stackademic

The leading education platform for anyone with an interest in software development.

Microservices

Structuring a system as small, independently deployable services

Overview

Microservices split an application into small services owned by separate teams, each with its own codebase, deployment, and usually its own database. The goal is independent deployability and scaling, letting teams ship without coordinating a single monolith release. The cost is distributed-systems complexity: network failures, data consistency, and operational overhead that a monolith never faces, so many systems should start as a well-structured monolith.

Syntax / Usage

Services communicate over the network—synchronously via APIs or asynchronously via events. Each service owns its data; other services must go through its API rather than touching its tables directly (database-per-service).

[ API Gateway ]
      |-----------------------------|
      v                             v
[ Orders svc ]  --event-->  [ Inventory svc ]
      |  owns orders DB           |  owns inventory DB
      v                           v
   [ Orders DB ]              [ Inventory DB ]

Because each service has its own database, cross-service transactions use the saga pattern: a sequence of local transactions with compensating actions to undo prior steps on failure, instead of a single distributed lock.

Examples

An online store separates Orders, Payments, and Shipping. Orders publishes an event on checkout; Payments and Shipping react independently, and each scales to its own load profile.

A streaming platform splits recommendations, playback, and billing so a spike in playback traffic scales only that service, without over-provisioning billing.

A checkout saga charges the card, reserves stock, then schedules delivery; if stock reservation fails, a compensating transaction refunds the charge to keep the system consistent without a global transaction.

Common Mistakes

  • Splitting into services too early, paying distributed-systems tax before you need it
  • Sharing one database across services, recreating a monolith with network latency ("distributed monolith")
  • Using synchronous call chains everywhere, so one slow service cascades failures
  • Ignoring observability—distributed tracing and centralized logs are essential, not optional
  • Trying to keep strong ACID transactions across services instead of embracing sagas and eventual consistency

See Also

system-design-apis system-design-message-queues system-design-scalability