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-08-02 by Shubham Bhati — Backend Engineer (Java 17, Spring Boot, Microservices).

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

Remember the early days of microservices? Deploying a dozen services only to realize they could not find each other without hardcoding IP addresses and ports? What a nightmare when scaling, deploying new versions, or handling failures! Manual updates to configuration files became a bottleneck, making continuous deployment feel like a distant dream. This problem is precisely what service discovery solves, enabling services to dynamically find and communicate with one another. In this spring cloud eureka tutorial, we will get our hands dirty setting up a Eureka server and clients to bring order to your microservice chaos.

Setting Up Your Eureka Server

The Eureka Server acts as a central registry where all your microservices register themselves. It keeps track of service instances, their locations, and health statuses. Building one with Spring Boot is surprisingly straightforward. You start by adding the spring-cloud-starter-netflix-eureka-server dependency to your pom.xml. Then, simply annotate your main application class with @EnableEurekaServer.

<!-- pom.xml -->
<dependency>
    <groupId>org.springframework.cloud</groupId>
    <artifactId>spring-cloud-starter-netflix-eureka-server</artifactId>
</dependency>
Enter fullscreen mode Exit fullscreen mode
// EurekaServerApplication.java
@SpringBootApplication
@EnableEurekaServer
public class EurekaServerApplication {
    public static void main(String[] args) {
        SpringApplication.run(EurekaServerApplication.class, args);
    }
}
Enter fullscreen mode Exit fullscreen mode

Next, configure the server in your application.yml. You generally want to disable registration and fetching from itself, as it's the server. It is typically a lean service, so its memory footprint is low, consuming only what's needed for the registry data. But watch out for port conflicts if you run multiple services on the same host during local development.

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

eureka:
  client:
    register-with-eureka: false
    fetch-registry: false
Enter fullscreen mode Exit fullscreen mode

Registering a Client Service

Now that our Eureka server is ready, client microservices can register themselves. This means they broadcast their network location and status to the registry. To enable this in a Spring Boot service, add the spring-cloud-starter-netflix-eureka-client dependency. Crucially, annotate your main application class with @EnableDiscoveryClient.

<!-- pom.xml -->
<dependency>
    <groupId>org.springframework.cloud</groupId>
    <artifactId>spring-cloud-starter-netflix-eureka-client</artifactId>
</dependency>
Enter fullscreen mode Exit fullscreen mode
// MyServiceClientApplication.java
@SpringBootApplication
@EnableDiscoveryClient
public class MyServiceClientApplication {
    public static void main(String[] args) {
        SpringApplication.run(MyServiceClientApplication.class, args);
    }
}
Enter fullscreen mode Exit fullscreen mode

In your client service's application.yml, point it to your Eureka server. You will also give your service an application-name which other services will use to find it. The Eureka client intelligently caches the service registry, which makes your service more resilient to temporary Eureka server outages. This local cache minimizes registration latency and reduces direct dependencies on the server for every service lookup.

# application.yml for Client Service
spring:
  application:
    name: my-service-client

eureka:
  client:
    serviceUrl:
      defaultZone: http://localhost:8761/eureka/
  instance:
    # Use service name + random value for unique instance IDs
    instance-id: ${spring.application.name}:${random.value}
Enter fullscreen mode Exit fullscreen mode

Consuming Services with Eureka and RestTemplate

Once client services are registered, other services can discover and communicate with them using their logical service names instead of fixed URLs. Spring Cloud simplifies this with @LoadBalanced RestTemplate or WebClient.Builder. When you mark a RestTemplate bean with @LoadBalanced, Spring Cloud automatically intercepts calls, resolves the service name using Eureka, and applies client-side load balancing.

// Configuration class in calling service
@Configuration
public class AppConfig {

    @Bean
    @LoadBalanced
    public RestTemplate restTemplate() {
        return new RestTemplate();
    }
}
Enter fullscreen mode Exit fullscreen mode

Now, in any component, you can inject this RestTemplate and call services by their spring.application.name.

// Service component calling 'my-service-client'
@Service
public class MyCallingService {

    private final RestTemplate restTemplate;

    public MyCallingService(@LoadBalanced RestTemplate restTemplate) {
        this.restTemplate = restTemplate;
    }

    public String callMyServiceClient() {
        // 'my-service-client' is the spring.application.name of the target service
        return restTemplate.getForObject("http://my-service-client/api/hello", String.class);
    }
}
Enter fullscreen mode Exit fullscreen mode

For production, consider customizing the underlying HTTP client for your RestTemplate (e.g., Apache HttpClient) or WebClient (e.g., Reactor Netty) to fine-tune connection pooling, timeouts, and retry logic. Default settings can impact latency p99 and thread utilization, especially under heavy load. Properly configured connection pools are crucial for maintaining performance and resource efficiency across microservice calls.

Common Pitfalls

  • Forgetting @EnableEurekaServer or @EnableDiscoveryClient: This is a common oversight. Without these annotations, your application won't behave as a Eureka server or client.
  • Incorrect application.name: Other services locate your service using this name. Mismatches or typos prevent proper discovery.
  • Missing or Incorrect defaultZone: Ensure your client services point to the correct Eureka server URL in their configuration. A simple typo can make clients unable to register.
  • Firewall Issues: If Eureka server and client services are on different machines, make sure network firewalls allow communication on their respective ports (default 8761 for Eureka).
  • Default instance-id collision: When running multiple instances of the same service on the same host for local testing, Eureka needs unique instance-ids. Using ${spring.application.name}:${random.value} helps here.

Conclusion

You have now set up a basic, yet functional, service discovery mechanism using Spring Cloud Eureka. This pattern eliminates hardcoded URLs, simplifies scaling, and improves the overall resilience of your microservice architecture. By understanding the core components—the Eureka Server and its clients—and how to consume services, you are well-equipped to manage complex deployments. Next, explore client-side load balancing customization and resilience patterns like circuit breakers to make your microservices even more robust.


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)