100% Free Forever
AI-Powered Learning
Industry Expert Content
Certificates & Badges
Learn At Your Own Pace
Software Architecture

Service Discovery Explained

Understand how microservices find and communicate with each other dynamically, using service registries, health checks, and DNS-based discovery.

InfrastructureIntermediate9 min readJul 10, 2026
Analogies

Why Service Discovery Matters

In a microservices system running on containers or cloud instances, service locations change constantly — instances are added during autoscaling, replaced after crashes, or rescheduled to a different host by an orchestrator. Hardcoding IP addresses in configuration files breaks the moment any instance moves, so services need a way to find each other dynamically at runtime. Service discovery solves this by maintaining an up-to-date, queryable record of which instances of a service are currently healthy and where they live.

🏏

Cricket analogy: This is like a cricket team's substitute fielder position changing every over as the captain like Rohit Sharma rotates players, so teammates must check the current fielding chart rather than assume someone is still at cover.

Client-Side vs Server-Side Discovery

In client-side discovery, the calling service queries a registry like Netflix Eureka directly and then picks an instance itself, often using a client-side load-balancing library such as Netflix Ribbon; this keeps the extra hop out of the request path but requires every client to embed discovery logic. In server-side discovery, the client simply calls a fixed address, and a load balancer or router (like an AWS Application Load Balancer or a Kubernetes Service) queries the registry and forwards the request; this is simpler for clients but adds an extra network hop through the router.

🏏

Cricket analogy: Client-side discovery is like a batter checking the fielding placements themselves before deciding where to hit, while server-side is like trusting the non-striker to call 'yes' or 'no' for a run based on what they see.

Example: Registering with Consul

json
{
  "service": {
    "name": "payments-service",
    "id": "payments-service-01",
    "address": "10.0.4.22",
    "port": 8090,
    "check": {
      "http": "http://10.0.4.22:8090/health",
      "interval": "10s",
      "timeout": "2s"
    },
    "tags": ["v2", "primary"]
  }
}

Most service registries, including Consul and Eureka, deregister an instance automatically after a configurable number of consecutive failed health checks, which is why setting the interval and timeout correctly matters — too aggressive and you deregister healthy instances during a brief GC pause; too lax and traffic keeps flowing to a dead instance.

Service Registry and Health Checks

The registry is the database at the heart of service discovery, storing which instances exist, their network addresses, and metadata like version tags used for canary releases. Registration can be self-registration, where each service instance calls the registry on startup and sends periodic heartbeats, or third-party registration, where a separate registrar process (like a Kubernetes controller) observes the platform and updates the registry on the service's behalf. Health checks are what keep the registry trustworthy — an instance that is registered but unresponsive must be pulled out of rotation quickly so clients don't keep sending traffic to a dead or degraded node.

🏏

Cricket analogy: This is like a team manager keeping an official injury list updated in real time, so the selectors don't pick a player like an injured fast bowler who is actually unavailable for the next match.

Relying purely on a TCP-level health check (is the port open?) is not enough — a service can accept connections while its downstream database connection is broken. Use application-level health endpoints that verify critical dependencies, and be careful that the health check itself doesn't cascade failures by overloading a dependency during an incident.

DNS-Based Discovery in Kubernetes

Kubernetes bakes service discovery into the platform itself: every Service object gets a stable DNS name like payments-service.default.svc.cluster.local, resolved by the cluster's internal DNS (CoreDNS) to a virtual IP that load-balances across healthy pod endpoints. This means application code rarely needs to talk to a registry API directly — it just does a normal DNS lookup and an HTTP call, and kube-proxy or the CNI plugin handles routing to whichever pod is currently healthy, with the Kubernetes control plane automatically removing pods that fail their readiness probes from the Service's endpoint list.

🏏

Cricket analogy: This is like calling a stadium by its well-known name, such as 'Eden Gardens', and letting the city's road network route you there, rather than needing the exact GPS coordinates of the current pitch.

  • Service discovery lets microservices find each other dynamically as instances move, scale, or restart.
  • Client-side discovery has the caller query the registry directly; server-side discovery routes through a load balancer.
  • Tools like Consul and Netflix Eureka implement registries with heartbeats and health checks.
  • Application-level health checks are more reliable than simple TCP port checks.
  • Kubernetes provides built-in DNS-based service discovery via Service objects and CoreDNS.
  • Unhealthy or unresponsive instances must be deregistered quickly to avoid routing traffic to dead nodes.
  • Registries can use self-registration or third-party registration depending on the platform.

Practice what you learned

Was this page helpful?

Topics covered

#SoftwareArchitecture#MicroservicesStudyNotes#SoftwareEngineering#ServiceDiscoveryExplained#Service#Discovery#Explained#Matters#StudyNotes#SkillVeris