Question 8 · Section 17

What is the difference between client-side and server-side discovery

least-connections, by availability zone). With server-side discovery this decision is made by the LB, and the client cannot influence it.

Language versions: English Russian Ukrainian

Junior Level

Client-side discovery:

Service A asks the Registry itself and calls Service B
Service A -> Registry: "Where is service B?" -> 10.0.0.5:8080 -> call

Server-side discovery:

Service A calls the Load Balancer, and the LB finds Service B
Service A -> Load Balancer -> Registry -> Service B

Difference: who makes the request to the Registry — the client or the server (LB).


Middle Level

Client-side

// Service A looks up service B itself
ServiceRegistry registry = new ConsulRegistry("consul:8500");
ServiceInstance instance = registry.getInstance("service-b");

HttpClient client = HttpClient.newBuilder()
    .connectTimeout(Duration.ofSeconds(5))
    .build();

HttpResponse<String> response = client.send(
    HttpRequest.newBuilder(URI.create("http://" + instance.getAddress() + "/api"))
        .GET().build(),
    BodyHandlers.ofString()
);

Pros:

  • More control: the service itself decides which instance to choose (round-robin, least-connections, by availability zone). With server-side discovery this decision is made by the LB, and the client cannot influence it.
  • No additional hop through LB

Cons:

  • Need to implement discovery logic in each service
  • Dependency on Registry SDK

Server-side

Service A -> Load Balancer (Nginx/HAProxy) -> Service B

# Nginx config
# In production, Nginx Plus or consul-template dynamically update upstreams.
# Static IPs — simplification for the example.
upstream service_b {
    server 10.0.0.5:8080;
    server 10.0.0.6:8080;
}

Pros:

  • Simpler for clients
  • LB handles discovery and balancing

Cons:

  • Additional hop (latency)
  • LB — single point of failure

Common mistakes

  1. Client-side: caching without TTL:
    Service A cached service B's IP
    Service B moved to a new IP
    Service A hits the old IP
    

Senior Level

Architectural Trade-offs

Client-side Server-side
No single point of failure LB can go down
More complex to implement Simpler
Less latency +1 hop
Flexibility (retry, circuit breaker) Less control

Production Experience

Kubernetes (server-side):

K8s Services -> kube-proxy -> Endpoints
Service A -> my-service:8080 -> kube-proxy -> Pod B

Netflix Ribbon (client-side): ⚠️ Netflix Ribbon is deprecated (in maintenance mode since 2018). In modern projects, use Spring Cloud LoadBalancer or K8s Service.

@LoadBalanced
@Bean
public RestTemplate restTemplate() {
    return new RestTemplate();
}

// Ribbon handles discovery + load balancing
restTemplate.getForObject("http://service-b/api", String.class);

Best Practices

✅ Client-side: caching with TTL
✅ Server-side: multiple LBs for HA
✅ Health checks in both cases
✅ Fallback when Registry is unavailable

❌ Without caching (too many Registry calls)
❌ Without fallback when LB is unavailable

Interview Cheat Sheet

Must know:

  • Client-side: service asks the Registry itself and chooses the instance (round-robin, least-connections)
  • Server-side: LB handles discovery and balancing (Nginx, K8s Service)
  • Client-side: no extra hop, but need to implement logic in each service
  • Server-side: simpler for clients, but +1 hop and LB is a potential SPOF
  • Netflix Ribbon is deprecated (maintenance mode since 2018) — use Spring Cloud LoadBalancer
  • Client-side caching is MANDATORY with TTL, otherwise stale IP
  • K8s uses server-side: kube-proxy -> Endpoints

Common follow-up questions:

  • When to choose client-side? Need flexibility (retry, circuit breaker), minimal latency.
  • When to choose server-side? Simpler, when the team doesn’t want to write discovery logic.
  • What happens without TTL in cache? Service moved to a new IP — client hits the old one.
  • What type is K8s? Server-side: Service -> DNS -> kube-proxy -> Pod.

Red flags (DO NOT say):

  • “Netflix Ribbon is the best choice” — deprecated, use Spring Cloud LoadBalancer
  • “Caching is not needed, Registry is fast” — unnecessary load on Registry with every call
  • “Server-side is always better” — depends on flexibility requirements
  • “LB never goes down” — need HA (multiple LBs)

Related topics:

  • [[7. What is Service Discovery and why is it needed]]
  • [[9. What is API Gateway and what problems does it solve]]
  • [[12. How to implement horizontal scaling of microservices]]
  • [[26. What tools are used for microservice orchestration]]
  • [[16. What is the difference between synchronous and asynchronous communication]]