Glossary

Microservices

Microservices is an architectural style where an application is built as a collection of small, independent services — each responsible for a specific business capability, communicating via APIs, and deployable independently.

Explanation

In a microservices architecture, instead of one large application (a monolith), you have many small services: User Service, Order Service, Payment Service, Notification Service. Each service has its own codebase, database, and deployment pipeline. Teams can develop and release their service without coordinating with other teams. Key properties: single responsibility (each service does one thing), independent deployability, independent scalability (scale only the services under load), polyglot persistence (each service uses the most appropriate database), and failure isolation (a crash in Notification Service doesn't take down everything). Microservices are not free: in-process function calls become network calls, introducing latency, partial failures, and distributed transaction complexity. You need service discovery, API gateways, distributed tracing (Jaeger, Zipkin), centralized logging, and container orchestration (Kubernetes). This overhead is justified for large organizations with many teams — but premature for small teams. The typical evolution: start with a monolith. Extract services when independent scaling or team autonomy justify it. Shopify, Stack Overflow, and Basecamp run significant monoliths at scale. 'Don't start with microservices' is near-universal advice from experienced engineers.

Code Example

javascript
// Microservice communication patterns

// 1. Synchronous: Order Service calls User Service via HTTP
async function getUser(userId) {
  const res = await fetch(`${process.env.USER_SERVICE_URL}/users/${userId}`, {
    headers: { Authorization: `Bearer ${getServiceToken()}` },
    signal: AbortSignal.timeout(3000), // always set timeouts
  });
  if (!res.ok) throw new Error(`User service: ${res.status}`);
  return res.json();
}

// 2. Asynchronous: Order Service publishes an event
await messageQueue.publish('order.placed', {
  orderId: order.id,
  userId:  order.userId,
  amount:  order.total,
});

// Notification Service subscribes (decoupled)
messageQueue.subscribe('order.placed', async (event) => {
  await sendEmail(event.userId, 'Your order has been placed!');
});

// Service boundaries rule: each service owns its data
// User Service: owns users table
// Order Service: owns orders table (copies user data it needs)
// NEVER: Order Service queries User Service's database directly

Why It Matters for Engineers

Microservices vs. monolith is one of the most important architectural decisions in software, and a common system design interview topic. Knowing when microservices are warranted vs. when a structured monolith is better demonstrates architectural judgment over following trends. Microservices also introduce distributed systems concepts — service discovery, eventual consistency, circuit breakers — that appear throughout systems design interviews and real architectures. Understanding them gives you a framework for reasoning about distributed system complexity.

Related Terms

Monolith · API · Message Queue · Docker

Learn This In Practice

Go deeper with the full module on Beyond Vibe Code.

Systems Design Fundamentals → →