Spring Cloud Eureka - Quick Reference

SkillAI & models

Netflix Eureka for service discovery in Spring Cloud microservices. Covers Eureka Server, Eureka Client, registration, and health checks.

Available today. Use it from your connected AI after setup.

Connect ahel once, and every AI you use reads what you have installed.

Then ask your AI: use the Spring Cloud Eureka - Quick Reference skill

What this skill tells your AI

The instructions your AI receives, as published by claude-dev-suite/claude-dev-suite in skills/backend-frameworks/spring-cloud-eureka/SKILL.md and read by ahel’s review.

Deep Knowledge: Use mcp__documentation__fetch_docs with technology: spring-cloud-eureka for comprehensive documentation.

Eureka Server Setup

Dependencies

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

Main Application

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

application.yml (Server)

server:
  port: 8761

spring:
  application:
    name: eureka-server

eureka:
  instance:
    hostname: localhost
  client:
    register-with-eureka: false  # Don't register itself
    fetch-registry: false         # Don't fetch registry
    service-url:
      defaultZone: http://${eureka.instance.hostname}:${server.port}/eureka/
  server:
    enable-self-preservation: true
    eviction-interval-timer-in-ms: 5000
    renewal-percent-threshold: 0.85

High Availability (Peer Replication)

# eureka-server-1
server:
  port: 8761

eureka:
  instance:
    hostname: eureka1.mycompany.com
  client:
    register-with-eureka: true
    fetch-registry: true
    service-url:
      defaultZone: http://eureka2.mycompany.com:8762/eureka/,http://eureka3.mycompany.com:8763/eureka/

---
# eureka-server-2
server:
  port: 8762

eureka:
  instance:
    hostname: eureka2.mycompany.com
  client:
    service-url:
      defaultZone: http://eureka1.mycompany.com:8761/eureka/,http://eureka3.mycompany.com:8763/eureka/

Eureka Client Setup

Dependencies

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

application.yml (Client)

spring:
  application:
    name: user-service

server:
  port: 8081

eureka:
  client:
    service-url:
      defaultZone: http://localhost:8761/eureka/
    registry-fetch-interval-seconds: 5
    initial-instance-info-replication-interval-seconds: 5
  instance:
    instance-id: ${spring.application.name}:${random.value}
    prefer-ip-address: true
    lease-renewal-interval-in-seconds: 10
    lease-expiration-duration-in-seconds: 30
    metadata-map:
      version: ${project.version:unknown}
      zone: zone-a

Instance Health

eureka:
  instance:
    health-check-url-path: /actuator/health
    status-page-url-path: /actuator/info

Service Discovery

Using DiscoveryClient

@Service
@RequiredArgsConstructor
public class ServiceDiscoveryService {

    private final DiscoveryClient discoveryClient;

    public List<ServiceInstance> getInstances(String serviceName) {
        return discoveryClient.getInstances(serviceName);
    }

    public String getServiceUrl(String serviceName) {
        List<ServiceInstance> instances = discoveryClient.getInstances(serviceName);
        if (instances.isEmpty()) {
            throw new ServiceNotFoundException(serviceName);
        }
        // Simple random selection
        ServiceInstance instance = instances.get(
            ThreadLocalRandom.current().nextInt(instances.size()));
        return instance.getUri().toString();
    }

    public List<String> getAllServices() {
        return discoveryClient.getServices();
    }
}

Using RestTemplate with LoadBalancer

@Configuration
public class RestTemplateConfig {

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

@Service
@RequiredArgsConstructor
public class UserClient {

    private final RestTemplate restTemplate;

    public User getUser(Long id) {
        // Uses service name instead of hostname
        return restTemplate.getForObject(
            "http://USER-SERVICE/api/users/{id}",
            User.class, id);
    }
}

Using WebClient with LoadBalancer

@Configuration
public class WebClientConfig {

    @Bean
    @LoadBalanced
    public WebClient.Builder webClientBuilder() {
        return WebClient.builder();
    }
}

@Service
public class UserWebClient {

    private final WebClient webClient;

    public UserWebClient(WebClient.Builder builder) {
        this.webClient = builder.baseUrl("http://USER-SERVICE").build();
    }

    public Mono<User> getUser(Long id) {
        return webClient.get()
            .uri("/api/users/{id}", id)
            .retrieve()
            .bodyToMono(User.class);
    }
}

Custom Load Balancer

@Configuration
public class CustomLoadBalancerConfig {

    @Bean
    public ReactorLoadBalancer<ServiceInstance> customLoadBalancer(
            Environment environment,
            LoadBalancerClientFactory clientFactory) {

        String name = environment.getProperty(LoadBalancerClientFactory.PROPERTY_NAME);

        return new RoundRobinLoadBalancer(
            clientFactory.getLazyProvider(name, ServiceInstanceListSupplier.class),
            name);
    }
}

// Apply to specific service
@LoadBalancerClient(name = "USER-SERVICE", configuration = CustomLoadBalancerConfig.class)
public class UserServiceConfig {
}

Zone-Aware Routing

# Service in zone-a
eureka:
  instance:
    metadata-map:
      zone: zone-a
  client:
    prefer-same-zone-eureka: true
    availability-zones:
      region1: zone-a,zone-b
    region: region1
@Bean
public ServiceInstanceListSupplier zonePreferenceSupplier(
        ConfigurableApplicationContext context) {
    return ServiceInstanceListSupplier.builder()
        .withDiscoveryClient()
        .withZonePreference()
        .build(context);
}

Health and Status

Custom Status

@Component
public class CustomHealthIndicator extends AbstractHealthIndicator {

    @Override
    protected void doHealthCheck(Health.Builder builder) {
        // Custom health logic
        if (isHealthy()) {
            builder.up().withDetail("custom", "OK");
        } else {
            builder.down().withDetail("custom", "FAILING");
        }
    }
}

Force Status

@Autowired
private ApplicationInfoManager applicationInfoManager;

public void setOutOfService() {
    applicationInfoManager.setInstanceStatus(InstanceStatus.OUT_OF_SERVICE);
}

public void setUp() {
    applicationInfoManager.setInstanceStatus(InstanceStatus.UP);
}

REST Endpoints

# Eureka Server Dashboard
GET http://localhost:8761/

# Apps registered
GET http://localhost:8761/eureka/apps

# Specific app
GET http://localhost:8761/eureka/apps/{appName}

# Specific instance
GET http://localhost:8761/eureka/apps/{appName}/{instanceId}

# Instance status
PUT http://localhost:8761/eureka/apps/{appName}/{instanceId}/status?value=OUT_OF_SERVICE

# Delete instance
DELETE http://localhost:8761/eureka/apps/{appName}/{instanceId}

Security

Secure Eureka Server

# application.yml
spring:
  security:
    user:
      name: eureka
      password: ${EUREKA_PASSWORD}
@Configuration
@EnableWebSecurity
public class SecurityConfig {

    @Bean
    public SecurityFilterChain filterChain(HttpSecurity http) throws Exception {
        http.csrf(csrf -> csrf.ignoringRequestMatchers("/eureka/**"))
            .authorizeHttpRequests(auth -> auth
                .requestMatchers("/actuator/health").permitAll()
                .anyRequest().authenticated())
            .httpBasic(Customizer.withDefaults());
        return http.build();
    }
}

Secure Client Connection

eureka:
  client:
    service-url:
      defaultZone: http://eureka:${EUREKA_PASSWORD}@localhost:8761/eureka/

Docker/Kubernetes

Docker Compose

services:
  eureka:
    image: myorg/eureka-server
    ports:
      - "8761:8761"
    environment:
      - EUREKA_INSTANCE_HOSTNAME=eureka
      - EUREKA_CLIENT_SERVICEURL_DEFAULTZONE=http://eureka:8761/eureka/

  user-service:
    image: myorg/user-service
    environment:
      - EUREKA_CLIENT_SERVICEURL_DEFAULTZONE=http://eureka:8761/eureka/
      - EUREKA_INSTANCE_PREFER_IP_ADDRESS=true

Kubernetes (consider using K8s native discovery)

eureka:
  instance:
    prefer-ip-address: true
    ip-address: ${POD_IP}
  client:
    service-url:
      defaultZone: http://eureka-server:8761/eureka/

Best Practices

DoDon't
Use prefer-ip-address in containersUse hostname in dynamic environments
Configure HA with peer replicationSingle Eureka server in production
Set proper lease intervalsUse default intervals in production
Use zone-aware routingIgnore network topology
Enable self-preservationDisable without understanding impact

Production Checklist

  • Eureka HA configured (3+ nodes)
  • Security enabled
  • Proper lease intervals set
  • Health check URL configured
  • prefer-ip-address for containers
  • Zone configuration if multi-DC
  • Self-preservation tuned
  • Monitoring/alerting setup
  • Client retry configured
  • Service instance metadata set

When NOT to Use This Skill

  • Kubernetes - Use K8s native service discovery
  • Consul preferred - Use Consul for service discovery
  • Simple setup - DNS-based discovery may suffice
  • Serverless - Not applicable

Anti-Patterns

Anti-PatternProblemSolution
Single Eureka instanceSingle point of failureDeploy peer-aware cluster
No health checksUnhealthy services listedEnable health indicator
Wrong renewal intervalLate detection of down servicesTune heartbeat settings
Ignoring self-preservationServices removed unexpectedlyUnderstand and tune
No secure registryUnauthorized registrationsAdd Spring Security

Quick Troubleshooting

ProblemDiagnosticFix
Service not registeringCheck Eureka dashboardVerify eureka.client.serviceUrl
Service listed as DOWNCheck health endpointFix health indicator
Stale registrationsCheck lease settingsReduce renewal interval
Self-preservation modeCheck networkTune or disable if appropriate
Cannot connect to peersCheck peer URLsVerify cluster configuration

Reference Documentation

Signals

GitHub stars
33
Forks
8
Last commit
Sep 2026
Advanced
Catalog kind
skill
Gateway key
spring-cloud-eureka
Source
github.com/claude-dev-suite/claude-dev-suite