Service Discovery
Definition
Service discovery is a live directory of which service instances are running and where. Instances register and keep saying they are alive, and callers look up healthy instances by name.
Why it exists
Instances start, stop and move all the time, so their addresses keep changing. Fixed addresses break on the first redeploy. A directory always has the current ones.
How it works
The three steps
- Register: an instance announces its name, host and port on startup.
- Heartbeat / health check: the registry keeps only instances that are alive.
- Lookup: a caller resolves the name to one or more instances.
Example code
Eureka with Spring Cloud
Registry server:
@SpringBootApplication
@EnableEurekaServer
public class DiscoveryServerApplication {
public static void main(String[] args) {
SpringApplication.run(DiscoveryServerApplication.class, args);
}
}
server:
port: 8761
eureka:
client:
register-with-eureka: false
fetch-registry: false
Client service (the Eureka client starter registers it automatically):
spring:
application:
name: inventory-service
eureka:
client:
service-url:
defaultZone: http://localhost:8761/eureka
instance:
prefer-ip-address: true
Calling by name with a load-balanced client:
@Configuration
class HttpClientConfig {
@Bean
@LoadBalanced
RestClient.Builder loadBalancedRestClientBuilder() {
return RestClient.builder();
}
}
@Service
class InventoryClient {
private final RestClient client;
InventoryClient(RestClient.Builder builder) {
this.client = builder.baseUrl("http://inventory-service").build();
}
Integer stockFor(String sku) {
return client.get().uri("/stock/{sku}", sku).retrieve().body(Integer.class);
}
}
@LoadBalanced adds an interceptor that replaces the host inventory-service with a concrete host:port chosen by Spring Cloud LoadBalancer (round-robin by default).
System design considerations
- Clients should tolerate stale entries with timeouts and retries
- Registry outages must not stop calls to already-known instances
- Protect against self-preservation modes that keep dead instances listed
Health, caching and self-preservation
- Clients cache the registry and refresh periodically (30 s default), so a dead instance can still be called briefly. Combine discovery with retries and circuit breakers.
- Eureka favours availability over consistency (AP): during a network partition it enters self-preservation and stops evicting instances to avoid mass removal, so stale entries are possible.
- Use Actuator health (
eureka.client.healthcheck.enabled=true) so an instance whose dependencies are down reportsDOWN.
When to use it, and when not
Use it when
- Instance addresses change dynamically outside Kubernetes
- You need client-side load balancing with health awareness
- You run a mixed environment of VMs and containers
Think twice when
- You run on Kubernetes, where Services and DNS already do this
- You add a registry for a handful of fixed services
- You treat the registry as perfectly consistent
Client-side versus server-side discovery
| Client-side (Eureka + Spring Cloud LoadBalancer) | Server-side (Kubernetes Service, cloud LB) | |
|---|---|---|
| Who picks the instance | The client library | The infrastructure |
| Language coupling | Needs a client library | None |
| Extra components | Registry to run | Provided by the platform |
On Kubernetes, you usually do not need Eureka: a Service gives a stable DNS name (http://inventory-service) and kube-proxy balances across ready pods. Interviewers like to hear that discovery is a pattern and that the platform may already implement it.
Common mistakes
- Treating the registry as always-correct; stale entries exist, so you need timeouts and retries.
- Registering with
localhostor a container-internal IP unreachable from other services. - Running a single Eureka server in production; run peers that replicate to each other.
- Using the registry for configuration; that is the job of the Config Server.
Interview questions
1. What is service discovery and why is it needed?
A registry-based mechanism letting services locate each other by logical name despite dynamic IPs, enabling scaling and failover without configuration changes.
2. Client-side versus server-side discovery?
Client-side: the caller queries the registry and balances itself. Server-side: a router or load balancer does the lookup. Kubernetes provides server-side discovery natively.
3. How does Eureka know an instance is down?
Instances send heartbeats every 30 s; after the lease expires (90 s default) the registry evicts them. Self-preservation can pause evictions.
4. Eureka vs Consul vs ZooKeeper?
Eureka: AP, simple, Netflix/Spring-native. Consul: registry plus health checks, key-value store and optionally CP via Raft. ZooKeeper: CP coordination service used for discovery in some stacks.
5. How does load balancing work with @LoadBalanced?
An interceptor resolves the service ID through the ServiceInstanceListSupplier and a ReactorLoadBalancer (round-robin, random or custom) before sending the request.
6. Do you need Eureka on Kubernetes?
Usually not. Use Kubernetes Service DNS; Spring Cloud Kubernetes can also read the API server if you need client-side behaviour.
Check yourself
1How does a registry know an instance has died?
2In client-side discovery, who picks the instance?
3On Kubernetes, what normally replaces a separate registry?
Key takeaways
- Discovery maps a logical name to live instances through register, heartbeat and lookup.
- Client-side (Eureka) and server-side (Kubernetes) achieve the same goal differently.
- Registries are eventually consistent; pair them with resilience patterns.
Finished this page? Track your progress (saved only in your browser).