# Service Discovery with Eureka in Spring Cloud: Complete Implementation Guide

> Implement service discovery with Eureka in Spring Cloud. Learn how Eureka enables automatic registration, health checks, and client-side discovery for microservices.

- Repository: [Doocs/advanced-java](https://github.com/doocs/advanced-java)
- Tags: tutorial
- Published: 2026-02-28

---

**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`](https://github.com/doocs/advanced-java/blob/main/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:**

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

```

**Application Class:**

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

```

**Application Configuration:**

```yaml
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:**

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

```

**Application Class:**

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

```

**Application Configuration:**

```yaml
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:**

```yaml
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:**

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

```

**Service Invocation:**

```java
@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`](https://github.com/doocs/advanced-java/blob/main/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`.