Skip to main content
Microservices · Topic 3 of 10

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​

  1. Register: an instance announces its name, host and port on startup.
  2. Heartbeat / health check: the registry keeps only instances that are alive.
  3. 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 reports DOWN.

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 instanceThe client libraryThe infrastructure
Language couplingNeeds a client libraryNone
Extra componentsRegistry to runProvided 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 localhost or 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​

Quick quiz3 questions

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.
Next topicConfig server

Finished this page? Track your progress (saved only in your browser).