How It Works: Microservices Architecture — A Practical Primer


Updated: 2025-08-24

Executive summary

Microservices split a system into independently deployable services around business capabilities. Done right, you get team autonomy and fault isolation. Done wrong, you get a distributed monolith with pager fatigue.

When they shine

- Many teams shipping in parallel
- Clear bounded contexts (billing, catalog, auth)
- Need to scale different parts independently
- Compliance boundaries or data residency per domain

When to avoid (or delay)

- Tiny team, simple product
- Heavy cross-service transactions
- Missing CI/CD, observability, or automation

Core design principles

- **Bounded contexts**: each service owns its data + API
- **Clear contracts**: OpenAPI/gRPC; semantic versioning
- **Idempotent, time-bounded ops**: timeouts, retries, backoff
- **Event-driven where it helps**: publish domain events instead of tight coupling

Service contracts

# OpenAPI snippet (YAML)
paths:
  /orders:
    post:
      operationId: createOrder
      requestBody:
        content: { application/json: { schema: { $ref: '#/components/schemas/NewOrder' } } }
      responses:
        '201': { description: Created, content: { application/json: { schema: { $ref: '#/components/schemas/Order' } } } }

Sync vs async communication

- Sync (HTTP/gRPC) for request/response paths; keep them fast and idempotent.
- Async (Kafka/NATS) for fan-out and eventual consistency; model events explicitly.

// Domain event (JSON)
{
  "event": "order.created",
  "idempotency_key": "ord_123",
  "occurred_at": "2025-08-24T12:00:00Z",
  "data": { "order_id": "123", "user_id": "u9", "total": 43.20 }
}

Data ownership & duplication

- Each service owns its schema. Share via events or read models, not cross-service joins.
- Duplicate read-optimized data; document provenance and refresh rules.

Transactions & sagas

- Prefer local transactions per service; coordinate via saga (choreography or orchestration).
- Compensate instead of trying to ACID across services.

Resilience patterns

# Pseudo-config
timeouts:
  default: 800ms
retries:
  attempts: 2
  backoff: exponential 100ms..1s
circuit_breaker:
  error_threshold: 50%
  open_interval: 30s

Observability

- Logs: structured JSON with request_id and user_id (if safe)
- Metrics: RED/USE (rate, errors, duration / utilization, saturation, errors)
- Traces: propagate W3C trace context; sample intelligently

Security & trust boundaries

- Zero-trust between services: mTLS, per-service identities
- AuthZ at the edge (gateway) and again in services (defense in depth)
- Secrets management: vault/KMS; short-lived tokens; rotate certs

Deployment model (Kubernetes sketch)

# One Deployment + Service per microservice; API gateway at the edge
apiVersion: apps/v1
kind: Deployment
metadata: { name: catalog }
spec:
  replicas: 2
  selector: { matchLabels: { app: catalog } }
  template:
    metadata: { labels: { app: catalog } }
    spec:
      containers:
      - name: app
        image: registry.local/catalog:1.2.3
        ports: [{ containerPort: 8080 }]

---
apiVersion: v1
kind: Service
metadata: { name: catalog }
spec: { selector: { app: catalog }, ports: [{ port: 80, targetPort: 8080 }] }

API gateway responsibilities (if you use one)

- TLS termination, routing, rate limiting
- AuthN/AuthZ (JWT/sessions), CSRF for browser flows
- WebSockets, compression, header normalization

Local development

- Run services with docker-compose or tilt; seed databases; provide fake providers.
- Contract tests against stored OpenAPI/gRPC schemas.

Migration path from a monolith

- Carve out a thin edge (BFF/API gateway), then strangle one bounded context at a time.
- Keep one source of truth for user/session during the transition.
- Move DB ownership last; use change-data-capture for new read models.

Anti-patterns to dodge

- Shared database across “services”
- Chatty synchronous chains (N calls per request)
- Out-of-band manual deploy steps (breaks autonomy)

Taylor Swift

“We are never ever getting back together.” — chorus


Comments

Popular posts from this blog

Learning to Automate My Side Projects with SWE-agent + GitLab

Ship-Ready Web Essentials: Search, Sitemap, Metadata & Icons (SvelteKit)

Kubernetes Secrets Management — SOPS + age (GitOps‑friendly)