Service discovery: how services find each other

When servers start, stop and move all the time, hard-coded addresses break. Service discovery keeps a live map of who is where.

A directory pointing to several services

In a small system, service A calls service B at a fixed address. In a cloud or container setup, instances start, stop, scale and move constantly, and their IP addresses change. Service discovery is the mechanism that lets a caller find a healthy instance of the service it needs.

The service registry

A registry is a live list of service names and the addresses of their healthy instances. Examples: Consul, etcd, ZooKeeper, Eureka, and the built-in registry in Kubernetes.

  1. Registration: an instance tells the registry "I am orders at 10.0.3.7:8080", either itself or through a platform agent.
  2. Health checks: the registry pings instances (or expects heartbeats) and removes dead ones.
  3. Lookup: callers ask the registry for current addresses.

Two patterns

Client-side discovery. The caller queries the registry, gets a list and picks one instance itself (often with its own load balancing). Fewer hops, but every client needs the logic.

Server-side discovery. The caller sends the request to a stable address (a load balancer or proxy), which asks the registry and forwards it. Clients stay simple. Kubernetes Services work this way.

DNS-based discovery

The simplest version: a service name resolves through DNS to current instance IPs. It is easy and universal. The catches are DNS caching (clients may keep a dead address for a while) and the lack of rich health information, so keep TTLs short.

Things to get right

  • Fail fast on dead instances: use short health-check intervals and client-side timeouts and retries.
  • Registry availability: the registry is critical. Run it as a cluster, and let clients cache the last known list so a registry outage does not stop traffic.
  • Graceful shutdown: deregister before stopping so no request hits a closing instance.
  • Security: only trusted services should register, or an attacker could redirect traffic.

Takeaway: never hard-code instance addresses. Use a registry or the platform's built-in discovery, with health checks and cached results.


System Design series, Part 2 (building blocks): topic 11 of 14. Previous: Distributed locks: how to build one and why it is hard.

Keep reading