Service Discovery with Eureka in Spring Cloud: Complete Implementation Guide

Eureka provides a REST-based service registry that handles automatic service registration, heartbeat-driven health checks, and client-side service discovery for Spring Cloud microservices architectures.

This guide explains how to implement service discovery with Eureka in Spring Cloud using the doocs/advanced-java repository as a reference. You will learn the internal mechanics of the Eureka server, registration lifecycle, and practical configuration steps for production-ready microservices.

How Eureka Service Discovery Works

Eureka is the service registry component within Spring Cloud Netflix. It maintains a dynamic directory of all running microservice instances and enables clients to locate services without hardcoded URLs. The architecture consists of two primary roles:

  • Eureka Server – The central registry that stores service instance metadata and handles registration queries. Annotated with @EnableEurekaServer.
  • Eureka Client – Any microservice that registers itself (service provider) or queries the registry (service consumer). Annotated with @EnableEurekaClient.

According to the doocs/advanced-java documentation in docs/micro-services/how-eureka-enable-service-discovery-and-service-registration.md, the entire process follows a RESTful HTTP protocol with specific endpoints for registration, renewal, and discovery.

Service Registration Flow

When a Spring Boot application starts with Eureka Client enabled, it executes the following registration sequence:

  1. Initial Registration – The client sends a POST request to ApplicationResource.addInstance on the Eureka server. The payload includes instance metadata such as IP address, port, health-check URL, and custom metadata.
  2. Registry Storage – The server delegates to PeerAwareInstanceRegistryImpl.register, which stores the instance in a nested Map structure keyed by application name and instance ID.
  3. Peer Replication – The registration is asynchronously replicated to peer Eureka servers via the replicateToPeers method to ensure high availability across the cluster.

Heartbeat Mechanism and Health Checks

Eureka uses a lease-based model to track instance health. Every client must periodically renew its registration:

  • The client issues a PUT request to InstanceResource.renewLease every eureka.instance.lease-renewal-interval-in-seconds (default 30 seconds).
  • The server updates the lease timestamp and replicates the renewal to peer nodes.
  • If the server does not receive a renewal within eureka.instance.leaseExpirationDurationInSeconds (default 90 seconds), the instance becomes eligible for eviction.

Instance Eviction and Failover

A background evictionTimer task runs every eureka.server.evictionIntervalTimerInMs (default 60 seconds) to remove expired instances:

  • Instances that fail to renew their lease within the expiration window are evicted from the registry.
  • Consumers automatically stop receiving traffic for evicted instances, enabling rapid failover.
  • The eviction process is replicated across the peer-to-peer cluster to maintain consistency.

Service Discovery Flow for Consumers

Service consumers interact with Eureka to locate provider instances:

  1. Initial Fetch – On startup, the client calls DiscoveryClient.fetchRegistry, which sends a GET request to InstanceResource to retrieve the complete registry snapshot.
  2. Local Caching – The client caches the registry locally in memory to minimize network overhead.
  3. Periodic Refresh – Every eureka.client.registry-fetch-interval-seconds (default 30 seconds), the client re-fetches the registry to update its cache with new or removed instances.

Implementing the Eureka Server

To create a standalone Eureka Server, add the Spring Cloud Netflix dependency and enable the server annotation.

Maven Dependency:

<dependency>
    <groupId>org.springframework.cloud</groupId>
    <artifactId>spring-cloud-starter-netflix-eureka-server</artifactId>
</dependency>

Application Class:

@SpringBootApplication
@EnableEurekaServer
public class EurekaServerApplication {
    public static void main(String[] args) {
        SpringApplication.run(EurekaServerApplication.class, args);
    }
}

Application Configuration:

server:
  port: 8761

eureka:
  client:
    register-with-eureka: false
    fetch-registry: false
  server:
    eviction-interval-timer-in-ms: 60000

Setting register-with-eureka and fetch-registry to false prevents the server from attempting to register with itself.

Registering Microservices with Eureka Client

Service providers must include the Eureka Client dependency and configure their registration behavior.

Maven Dependency:

<dependency>
    <groupId>org.springframework.cloud</groupId>
    <artifactId>spring-cloud-starter-netflix-eureka-client</artifactId>
</dependency>

Application Class:

@SpringBootApplication
@EnableEurekaClient
public class ProviderApplication {
    public static void main(String[] args) {
        SpringApplication.run(ProviderApplication.class, args);
    }
}

Application Configuration:

server:
  port: 8081

spring:
  application:
    name: service-provider

eureka:
  client:
    service-url:
      defaultZone: http://localhost:8761/eureka/
    lease-renewal-interval-in-seconds: 30
    lease-expiration-duration-in-seconds: 90

The spring.application.name becomes the logical service ID used for discovery. Adjust lease-renewal-interval-in-seconds to control heartbeat frequency based on your network reliability requirements.

Consuming Services with DiscoveryClient

Consumers use the same Eureka Client dependency but focus on fetching registry information rather than publishing their own.

Application Configuration:

spring:
  application:
    name: service-consumer

eureka:
  client:
    service-url:
      defaultZone: http://localhost:8761/eureka/
    fetch-registry: true
    registry-fetch-interval-seconds: 30

RestTemplate Configuration with Ribbon:

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

Service Invocation:

@RestController
public class ConsumerController {

    @Autowired
    private RestTemplate restTemplate;

    @GetMapping("/call")
    public String callProvider() {
        return restTemplate.getForObject("http://service-provider/hello", String.class);
    }
}

The @LoadBalanced annotation enables client-side load balancing through Ribbon. When using the logical service name service-provider in the URL, Ribbon queries the local Eureka cache, selects an available instance, and replaces the hostname with the actual IP and port.

Summary

  • Eureka Server acts as the central registry using PeerAwareInstanceRegistryImpl to store instance data in memory-mapped structures and replicate changes via replicateToPeers.
  • Registration occurs via POST to ApplicationResource.addInstance on startup, followed by periodic PUT requests to InstanceResource.renewLease for heartbeats.
  • Service Discovery relies on DiscoveryClient.fetchRegistry to cache the registry locally and refresh every 30 seconds by default.
  • Eviction removes unhealthy instances after 90 seconds of missed heartbeats, executed by the evictionTimer task.
  • Spring Cloud abstracts HTTP interactions, requiring only @EnableEurekaClient and configuration properties to enable full service discovery capabilities.

Frequently Asked Questions

What is the default heartbeat interval for Eureka clients?

Eureka clients send heartbeat renewals every 30 seconds by default, controlled by the eureka.instance.lease-renewal-interval-in-seconds property. The server considers an instance expired if it misses renewals for 90 seconds (configurable via lease-expiration-duration-in-seconds).

How does Eureka handle server failures in a cluster?

Eureka servers replicate registration and renewal events to peer nodes asynchronously using the replicateToPeers method. If one server fails, clients automatically failover to other nodes configured in eureka.client.service-url.defaultZone, while cached registry data allows continued operation during brief outages.

Can a microservice be both a provider and a consumer in Eureka?

Yes. Any application annotated with @EnableEurekaClient simultaneously registers itself as a provider (via ApplicationResource.addInstance) and can discover other services (via DiscoveryClient.fetchRegistry). The dual role requires no additional configuration beyond standard Eureka Client setup.

Where is the complete architectural documentation for Eureka in the doocs/advanced-java repository?

The complete sequence diagrams and registry structure details are documented in docs/micro-services/how-eureka-enable-service-discovery-and-service-registration.md within the doocs/advanced-java repository, which illustrates the interaction between PeerAwareInstanceRegistryImpl, ApplicationResource, and InstanceResource.

Have a question about this repo?

These articles cover the highlights, but your codebase questions are specific. Give your agent direct access to the source. Share this with your agent to get started:

Share the following with your agent to get started:
curl -s "https://instagit.com/install.md"

Works with
Claude Codex Cursor VS Code OpenClaw Any MCP Client

Maintain an open-source project? Get it listed too →