What is service discovery, and how does Eureka (or an alternative) work?
Quick Answer
Service discovery lets services find each other by logical name rather than hardcoded network address: each service instance registers itself (its host, port, and health status) with a discovery server on startup, and a calling service asks that discovery server for the current, healthy instances of the service it wants to call, rather than relying on a static configuration file of addresses that would go stale as instances scale up/down or restart. Eureka (Netflix's implementation, integrated via Spring Cloud Netflix) is a classic choice; Kubernetes' built-in DNS-based service discovery, or Consul, are common alternatives, especially in container-orchestrated environments.
Detailed Answer
In a dynamic microservices environment, service instances are constantly starting, stopping, scaling, and moving between hosts — a static configuration file listing "Order Service is at 10.0.0.5:8080" would go stale almost immediately. Service discovery solves this by letting services find each other by logical name, resolved dynamically at call time.
How it typically works (using Eureka as the concrete example):
- Registration: each service instance, on startup, registers itself with the Eureka server (the discovery registry), reporting its host, port, and service name (
order-service), and sends periodic heartbeats to confirm it's still alive.
@SpringBootApplication
@EnableDiscoveryClient
class OrderServiceApplication { ... } // registers with Eureka on startup
eureka:
client:
service-url:
defaultZone: http://eureka-server:8761/eureka/
- Discovery: when Service A wants to call
order-service, instead of a hardcoded URL, it asks the Eureka client (a local cache, periodically refreshed from the Eureka server) for the current set of healthyorder-serviceinstances:
@Autowired DiscoveryClient discoveryClient;
List<ServiceInstance> instances = discoveryClient.getInstances("order-service");
More commonly, this is done transparently via a load-balanced RestTemplate/WebClient or OpenFeign client, which resolves the logical service name to an actual instance (and load-balances across multiple healthy instances) automatically, without the calling code ever handling raw addresses itself.
- Health/liveness tracking: if an instance stops sending heartbeats (crashed, network partition, scaled down), Eureka eventually evicts it from the registry, so calling services stop being routed to a dead instance.
Alternatives: Consul offers similar discovery capabilities (plus additional features like key-value config storage and health checking) and integrates with Spring Cloud similarly. In Kubernetes-based deployments, it's increasingly common to rely on Kubernetes' own built-in DNS-based service discovery (a Kubernetes Service resource provides a stable DNS name resolving to healthy pod IPs automatically) rather than adding a separate Eureka server, since the container orchestrator is already solving essentially the same problem at the infrastructure level.
Why this matters: without service discovery, scaling a service up/down, replacing an unhealthy instance, or moving services between hosts would require manually updating every other service's configuration to match — service discovery makes the whole system able to reconfigure itself dynamically as instances come and go.