DEV Community

Shubham Bhati
Shubham Bhati

Posted on

Service Discovery with Eureka and Spring Cloud: A Hands-On Tutorial

Spring Cloud Eureka Tutorial

Published 2026-07-30 by Shubham Bhati — Backend Engineer (Java 17, Spring Boot, Microservices).

Hey there, backend engineers! Shubham Bhati here.

Remember the dread of hardcoding service URLs in your microservices? Hardcoding meant every scale-up, every IP change, and every deployment required manual configuration updates across multiple services – a recipe for downtime and operational headaches. This approach quickly becomes unmanageable as your architecture grows. That's where Service Discovery shines, allowing services to find each other dynamically. Let's get hands-on with a spring cloud eureka tutorial to wire up this essential microservices registry.


Setting Up Your Central Eureka Server

The Eureka Server acts as the central registry where all your microservices register themselves. It keeps track of service instances, their locations, and their health status. Setting one up is straightforward. You'll create a standard Spring Boot application and enable Eureka functionality.

// EurekaServerApplication.java
package com.example.eurekaserver;

import org.springframework.boot.SpringApplication;
import org.springframework.boot.autoconfigure.SpringBootApplication;
import org.springframework.cloud.netflix.eureka.server.EnableEurekaServer;

@SpringBootApplication
@EnableEurekaServer // This annotation turns your Spring Boot app into a Eureka Server
public class EurekaServerApplication {
    public static void main(String[] args) {
        SpringApplication.run(EurekaServerApplication.class, args);
    }
}
Enter fullscreen mode Exit fullscreen mode

Now, configure its properties. We tell it not to register itself and disable fetching registries since it is the registry.

# application.yml for Eureka Server
server:
  port: 8761 # Default port for Eureka Server

eureka:
  instance:
    hostname: localhost
  client:
    register-with-eureka: false # Don't register the Eureka Server itself
    fetch-registry: false      # Don't fetch a registry from itself
    service-url:
      defaultZone: http://${eureka.instance.hostname}:${server.port}/eureka/
Enter fullscreen mode Exit fullscreen mode

Production Note: While simple, a single Eureka server is a Single Point of Failure (SPOF). For production, consider running multiple instances for high availability, perhaps behind a load balancer. Keep an eye on its memory footprint; as your microservices grow, the registry size increases. Also, think about thread pooling if you expect very high client registration/deregistration rates.


Registering Your Microservice with Eureka

Once your Eureka Server is up, your individual microservices need to register themselves. This makes them discoverable by other services.

First, add the Spring Cloud Eureka Client dependency to your pom.xml:

<!-- pom.xml snippet for client service -->
<dependency>
    <groupId>org.springframework.cloud</groupId>
    <artifactId>spring-cloud-starter-netflix-eureka-client</artifactId>
</dependency>
Enter fullscreen mode Exit fullscreen mode

Then, enable discovery in your application and configure it to point to your Eureka Server.

// MyServiceClientApplication.java
package com.example.myserviceclient;

import org.springframework.boot.SpringApplication;
import org.springframework.boot.autoconfigure.SpringBootApplication;
import org.springframework.cloud.client.discovery.EnableDiscoveryClient; // Enables client discovery

@SpringBootApplication
@EnableDiscoveryClient
public class MyServiceClientApplication {
    public static void main(String[] args) {
        SpringApplication.run(MyServiceClientApplication.class, args);
    }
}
Enter fullscreen mode Exit fullscreen mode

And its configuration:

# application.yml for My Service Client
spring:
  application:
    name: my-service # Unique name for your service, used for discovery

server:
  port: 8080 # Example port for your client service

eureka:
  client:
    service-url:
      defaultZone: http://localhost:8761/eureka/ # Point to your Eureka Server
  instance:
    hostname: localhost
    prefer-ip-address: true # Use IP address for registration
Enter fullscreen mode Exit fullscreen mode

Production Note: Eureka clients send heartbeats to the server to maintain their registration. Misconfigured eureka.client.lease-renewal-interval-in-seconds can lead to stale entries or premature eviction. For critical services, monitor registration status and ensure spring.application.name is unique and meaningful across your entire microservices architecture. Also, be aware of firewall rules; ensure your client services can reach the Eureka server's port.


Discovering and Consuming Services

With services registered, now how does one service find and call another? Spring Cloud simplifies this by integrating client-side load balancing and discovery.

You can inject Spring's DiscoveryClient directly, but a more common and convenient way is to use RestTemplate (or WebClient) with @LoadBalanced.

// Some other consuming service
package com.example.consumer;

import org.springframework.boot.SpringApplication;
import org.springframework.boot.autoconfigure.SpringBootApplication;
import org.springframework.cloud.client.discovery.EnableDiscoveryClient;
import org.springframework.context.annotation.Bean;
import org.springframework.web.client.RestTemplate;
import org.springframework.cloud.client.loadbalancer.LoadBalanced;

@SpringBootApplication
@EnableDiscoveryClient
public class ConsumerApplication {

    public static void main(String[] args) {
        SpringApplication.run(ConsumerApplication.class, args);
    }

    @Bean
    @LoadBalanced // Essential for client-side load balancing
    public RestTemplate restTemplate() {
        return new RestTemplate();
    }
}
Enter fullscreen mode Exit fullscreen mode

Now, in any component, you can use the RestTemplate to call my-service by its registered name:

// In a service class within ConsumerApplication
package com.example.consumer.service;

import org.springframework.stereotype.Service;
import org.springframework.web.client.RestTemplate;

@Service
public class MyConsumerService {

    private final RestTemplate restTemplate;

    public MyConsumerService(RestTemplate restTemplate) {
        this.restTemplate = restTemplate;
    }

    public String callMyService() {
        // Use the service name directly! RestTemplate resolves it via Eureka.
        return restTemplate.getForObject("http://my-service/api/data", String.class);
    }
}
Enter fullscreen mode Exit fullscreen mode

Production Note: Spring Cloud integrates client-side load balancing, crucial for distributing requests across multiple instances of a service and improving fault tolerance. This is automatically handled by the @LoadBalanced annotation. For very high-throughput scenarios, consider caching frequently accessed service instances locally to reduce repeated discovery calls, but be mindful of TTLs to avoid stale data. Monitor your network latency (p99) to ensure discovery isn't adding significant overhead.


Common Pitfalls to Avoid

  • Single Point of Failure for Eureka Server: Not deploying multiple Eureka instances. A single server means if it goes down, new service registrations fail and existing services can't update their status, eventually leading to stale information.
  • Misconfigured Client Heartbeats: Services either disappear from the registry too quickly or remain registered long after crashing. Tune lease-renewal-interval-in-seconds and lease-expiration-duration-in-seconds based on your service's health check frequency.
  • Ignoring spring.application.name: Not setting this property properly, or using non-unique names, leads to confusion and makes service lookup impossible or unreliable. It's the primary identifier for discovery.
  • Firewall Issues: Eureka server and client ports aren't open between different machines or within your containerized environment, preventing registration and discovery.
  • Not Using @LoadBalanced: Forgetting this annotation on your RestTemplate or WebClient.Builder means you won't get client-side load balancing, and direct service names won't resolve.

Conclusion

You've successfully wired up a powerful service discovery mechanism using Spring Cloud and Eureka. This foundational piece lets your microservices find each other dynamically, making your architecture scalable, resilient and much easier to manage. Keep building, innovating and deploying with confidence!


Spring Cloud Eureka Tutorial in production

Further Reading


Written by **Shubham Bhati* — Backend Engineer at AlignBits LLC, specializing in Java 17, Spring Boot, microservices, and AI integration. Connect on LinkedIn, GitHub, or read more at shubh2-0.github.io.*

Top comments (0)