Monoliths, Microservices & Service Discovery

Intermediate · 18 min read · High-Level Design, Services & Communication

When to split, service boundaries, discovery, API gateways and service meshes.

How you split a system into deployable units shapes almost everything else: how teams work, how failures spread, how data stays consistent, and how fast you can ship.

Three architectures

One deployable application containing all features, usually with one database.

Drawing service boundaries

Bad boundaries are worse than no boundaries — a distributed monolith where every change touches five services and they must deploy together.

Database per service

Each service owns its schema; other services access that data only through its API or events.

Service discovery

In dynamic environments, instances come and go with auto-scaling and deploys. Callers need current addresses.

API gateway and backend-for-frontend

An API gateway is the single entry point for external clients:

Service mesh

As service counts grow, every service needs retries, timeouts, mTLS, metrics and traffic shifting. A service mesh (Istio, Linkerd, Consul Connect) moves this into infrastructure:

Communication styles between services

A useful rule: synchronous for queries on the critical path, asynchronous for propagating state changes. Avoid long synchronous chains (A → B → C → D) — they multiply latency and failure probability. See Availability & Fault Tolerance.

Migrating from a monolith: the strangler fig

Don't rewrite from scratch. Put a routing layer in front of the monolith, extract one capability at a time into a service, route its traffic to the new service, and repeat until the monolith shrinks away (or what's left is fine as it is).

Interview questions

  • When would you choose a monolith over microservices?
  • Why shouldn't two services share a database?
  • What does a service mesh give you, and when is it not worth it?

Practice

Write your answer before opening the suggested one. Anything you mark "Partly" or "Missed it" comes back in your review deck.

Further reading

Key takeaways

  • Monoliths are simplest; modular monoliths add strong internal boundaries; microservices add independent deployment and scaling at a high operational cost.
  • Draw boundaries around business capabilities, and give each service ownership of its data.
  • Use service discovery (registry or platform DNS), an API gateway (or BFF) at the edge, and a service mesh only when the service count justifies it.
  • Prefer synchronous calls for critical-path queries and events for state propagation; avoid long call chains.
  • Migrate incrementally with the strangler fig pattern.

Previous: Message Queues & Event Streaming · Next: Event-Driven Architecture, CQRS & Event Sourcing