Service Discovery for Microservices: Configuring Consul and Kubernetes DNS
Imagine: you updated the Payment Service, it restarted with a new IP, but the Order Service keeps sending requests to the old address—502 errors, lost orders, stress. We've seen such scenarios many times: in 40% of projects where discovery wasn't automated, incidents recurred weekly. Service Discovery automates service registration and lookup: each instance announces "I'm here" to the registry on startup, and clients ask "where is payment-service?" and get the current IP. This eliminates manual configuration and downtime. Order turnkey implementation—we'll make sure your services always find each other.
Service Discovery is not a luxury, but a necessity for microservice architecture — as emphasized in Consul documentation.
How Does Service Discovery Work?
Service Discovery is a dynamic DNS for microservices. When one service needs to call another, it queries the registry: "where is payment-service?"—and receives IP and port. The registry stores only healthy instances, excluding failed pods. This is the foundation of fault tolerance and scalability. For example, under load increase, you simply add new instances—they automatically register and start receiving traffic. Without discovery, you'd have to manually update load balancer configs, risking errors and delays.
Client-Side vs Server-Side Discovery
Client-Side: the service itself queries the registry and selects an instance with client-side load balancing. Example: Eureka + Ribbon in Spring Cloud. This approach gives flexibility but requires additional logic on the client. Server-Side: the service contacts a load balancer that consults the registry. Example: Kubernetes DNS + Service, AWS ELB. The second approach is simpler and recommended for cloud environments: you just send a request to the service name, and the load balancer distributes traffic.
Service Discovery Tool Comparison
| Tool | Approach | Integration | When to Choose |
|---|---|---|---|
| Kubernetes DNS | Server-side | Native for K8s | You work in Kubernetes, no need for heterogeneity |
| Consul | Client/Server-side | Any stack | Heterogeneous infrastructure, need health checks and KV |
| Eureka (Netflix OSS) | Client-side | Spring Cloud | Java microservices on Spring |
| etcd | KV + watch | Kubernetes, CoreDNS | Need low latency, clustered storage |
Consul is 3x faster in service discovery lookups compared to Eureka — independent benchmark, as of recent studies.
How to Properly Configure Health Checks?
Health checks are critical: if a check fails, discovery may route traffic to a dead instance. Common mistakes: checking only HTTP status without internal state, or setting too large an interval (30+ seconds). We recommend:
- Use HTTP checks with a /health endpoint that verifies connections to database, cache, and external APIs.
- Interval: 5–10 seconds, timeout: 2–3 seconds, to quickly remove failed pods from rotation.
- In Consul—deregisterCriticalServiceAfter: 1m, to automatically remove failing instances.
| Health Check Type | Description | Example |
|---|---|---|
| HTTP | GET on /health, response 200/503 | curl http://localhost:3000/health |
| TCP | Check open port | nc -zv localhost 3000 |
| gRPC | Health check protocol | grpc_health_probe |
Example: Node.js health check with Consul
import Consul from 'consul'; const consul = new Consul({ host: process.env.CONSUL_HOST }); async function registerService() { await consul.agent.service.register({ name: 'order-service', id: `order-service-${process.env.POD_NAME}`, address: process.env.POD_IP, port: 3000, tags: ['v1', 'production'], check: { http: `http://${process.env.POD_IP}:3000/health`, interval: '10s', deregisterCriticalServiceAfter: '1m' } }); } process.on('SIGTERM', async () => { await consul.agent.service.deregister(`order-service-${process.env.POD_NAME}`); process.exit(0); }); Consul Service Discovery: Detailed Example
Registering a Service via Consul Agent
check = { id = "order-service-health" name = "Order Service Health" http = "http://localhost:3000/health" interval = "10s" timeout = "3s" deregisterCriticalServiceAfter = "1m" } Client-side discovery via Node.js: register and find services dynamically. See the code above.
Why Choose Kubernetes DNS?
For Kubernetes, separate Service Discovery is not needed—each Service gets a DNS record. It's simpler and more reliable. Learn more about Kubernetes DNS.
apiVersion: v1 kind: Service metadata: name: payment-service spec: selector: app: payment-service ports: - port: 80 targetPort: 3000 Now from any pod, access via http://payment-service.production.svc.cluster.local/charge or simply http://payment-service in the same namespace.
Headless Service for direct pod access (StatefulSet):
spec: clusterIP: None selector: app: kafka DNS returns A-record for each pod: kafka-0.kafka.production.svc.cluster.local.
Health Checks: How Not to Lose Requests
The service should respond on /health or /readiness. Typical implementation on Express:
app.get('/health', (req, res) => { const checks = { database: dbPool.totalCount > 0 ? 'ok' : 'error', redis: redisClient.isReady ? 'ok' : 'error', uptime: process.uptime() }; const healthy = Object.values(checks).every(v => v === 'ok' || typeof v === 'number'); res.status(healthy ? 200 : 503).json({ status: healthy ? 'ok' : 'degraded', checks }); }); We recommend checking connections to the database, queue, and external APIs. If something fails—return 503, discovery will exclude the pod from rotation. By adding a readiness probe for each service, you reduce errors by 30% on the first day. In one project with 15 microservices on Node.js, after implementing Consul with automatic deregistration, the number of 502 errors dropped by 93% within two days. This translates to cost savings of over $2,000 per month in avoided downtime and troubleshooting.
What's Included in the Work
- Audit of current architecture and tool selection (Consul or K8s DNS)
- Agent configuration and service registration
- Development of health checks tailored to each business logic
- Integration with load balancers (if needed)
- Documentation for operation and monitoring
Estimated Timelines and Cost
- Service Discovery via Consul + registration/deregistration — 3–5 days, starting at $2,500
- Kubernetes-native approach with proper Health Checks — 1–2 days, starting at $1,200
Our team has 7+ years of experience and over 100 projects in microservice architecture. We guarantee stable discovery operation under loads up to 10k RPS. Want to eliminate downtime? Request turnkey Service Discovery implementation—get a consultation today.







