Eureka: Microservice Registry

👉 Implementation guide for high-availability service Registry.


What is Spring Cloud Naming server ?

Spring Cloud Netflix Eureka is a high-availability Service Discovery and Naming Server that enables microservices to dynamically locate and communicate with each other without hardcoding network locations.

It’s a critical component in a distributed system that maintains a real-time list of active service instances and acts as a centralized “PhoneBook” where every service instance registers it’s metadata, such as IP address and port, during startup.

It serves as the “source of truth” for service locations, facilitating seamless communication, load balancing, and failover.


Why do we need a Naming Server ?

In modern cloud environments, microservice instances are ephemeral; they auto-scale, crash, or move to different nodes, resulting in unpredictable IP addresses.

Eureka operates on a Client-Server architecture designed for cloud resilience. Unlike traditional load balancers, it emphasizes “Client-Side Discovery”, where the intelligence of finding a service resides with the caller.

Key Components

  • Eureka Server (The Registry):
    • A central repository where services register their availability.
    • It maintains an in-memory map of service names to network locations.
  • Eureka Client (The Service):
    • Any microservice that registers with the server.
    • It also acts as a client to “fetch” the registry and find other services.
  • Heartbeats:
    • Periodic signals (default every 30s) sent from clients to the server to confirm they are still “alive.”

Advantage

  • Decoupling:
    • Services no longer need to know the specific host:port of their dependencies.
  • Dynamic Scaling:
    • New instances are automatically discovered as soon as they start.
  • High Availability:
    • It prevents traffic from being sent to “unhealthy” or “down” instances.

Setting up the Eureka Server

To build a production-grade Naming Server, develop a standalone Spring Boot application dedicated to registry management.

Maven dependencies

Include the Netflix Eureka Starter dependency in the pom.xml. This provides the core Eureka libraries and the web dashboard UI.

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

Enable the server

Add @EnableEurekaServer to main Spring Boot application class. This triggers the configuration required to turn your application into a registry.

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

3. Mandatory configuration

The Eureka Server requires specific properties to function correctly.

By default, Eureka attempts to register with itself; however, for a standalone server, this behavior must be disabled.

Configure the server port (standard port 8761) and disable client-side registration for the server itself.

spring:
  application:
    name: naming-service

server:
  port: 8761

eureka:
  client:
    # Standalone mode: Don't register with self or fetch registry
    register-with-eureka: false
    fetch-registry: false
PropertyDescription
register-with-eurekaSet to false so the server doesn’t appear in its own list of available services.
fetch-registrySet to false because the server is the primary source of truth and doesn’t need to pull data.
server.portThe default port 8761 is the convention for Eureka Discovery.

4. High Availability

In production grade apps, a single Eureka server is a bottleneck.

Eureka achieves High Availability by running multiple “Peer” instances that replicate the registry to each other. In Eureka, peers are not master-slave, they are all equal. When a client registers with Peer-1, Peer-1 uses a “replicate” task to push the registration to other peers.

Critical:
→ For a peer to successfully replicate, the spring.application.name must be identical across all nodes in the cluster.

Peer configuration

To set up a cluster, each Eureka server must point to its peers via the service-url.defaultZone property.

Below is the application configuration of 2 eureka instances pointing to each other.

Peer-1: application.yml

eureka:
  instance:
    hostname: peer1
  client:
    service-url:
      defaultZone: http://peer2:8762/eureka/

Peer-2: application.yml

eureka:
  instance:
    hostname: peer2
  client:
    service-url:
      defaultZone: http://peer1:8761/eureka/

Automate peer configuration

While the manual configuration outlined above works for a small static setup, the “best way” to handle peer configuration in a production environment involves a few key principles to ensure high availability and scalability.

Here is how to optimize peer-to-peer (P2P) setup.


1. DNS-Based Peer discovery

Instead of hardcoding specific IP addresses or hostnames in application config (YAML) files, the most robust method is to use DNS.

By using a DNS entry (like eureka-cluster.example.com) that resolves to multiple IP addresses, you don’t have to update every server’s configuration every time you add or remove a node from the cluster.


2. Using Spring Profiles

Instead of creating separate files for every peer, use Spring Profiles within a single application.yml. This allows to maintain one codebase, while easily switching identities at runtime.

A three-node circular cluster config
spring:
  application:
    name: eureka-server

eureka:
  client:
    # Ensures the server fetches the registry from peers on startup
    fetch-registry: true
    register-with-eureka: true
  instance:
    # High availability works best when hostnames are resolvable
    prefer-ip-address: false 

---
# Profile for Peer 1
spring:
  config:
    activate:
      on-profile: peer1
server:
  port: 8761
eureka:
  instance:
    hostname: peer1
  client:
    service-url:
      defaultZone: http://peer2:8762/eureka/,http://peer3:8763/eureka/

---
# Profile for Peer 2
spring:
  config:
    activate:
      on-profile: peer2
server:
  port: 8762
eureka:
  instance:
    hostname: peer2
  client:
    service-url:
      defaultZone: http://peer1:8761/eureka/,http://peer3:8763/eureka/

---
# Profile for Peer 3
spring:
  config:
    activate:
      on-profile: peer3
server:
  port: 8763
eureka:
  instance:
    hostname: peer3
  client:
    service-url:
      defaultZone: http://peer1:8761/eureka/,http://peer2:8762/eureka/

Peer config recommendations

To ensure your peer configuration is “best-in-class,” keep following settings in mind:

SettingRecommendationWhy?
Prefer IP Addresseureka.instance.prefer-ip-address: trueUseful in containerized environments (Docker/K8s) where hostnames can be volatile.
Sync Strategyeureka.server.registry-sync-retriesIncrease this value to ensure a booting server tries harder to pull the registry from its peers before timing out.
Self-Preservationeureka.server.enable-self-preservationKeep this enabled (default) in production to prevent mass-deregistration during network flickers.
Wait for Peerseureka.server.wait-time-in-ms-when-sync-emptySet this to a non-zero value (e.g., 5 mins) so the server waits to populate its registry from peers before serving traffic.

Observability and Health

The Eureka’s built-in Dashboard (available at http://:) is your primary tool for cluster monitoring.

This Dashboard provides:

  • Instance Status:
    • Real-time list of all microservices, their status (UP/DOWN), and metadata.
  • General Info:
    • Provides critical JVM metrics like memory usage and uptime.
  • Self-Preservation Mode:
    • A “Panic Mode” safety feature.
    • If Eureka loses contact with too many instances at once, it stops evicting them to protect the registry from network flickers.

Security

Exposing service registry is a significant security risk. The Naming Server must be secured to prevent unauthorized services from joining the cluster.

It can be secured using Spring Security:

  • Basic Auth:
    • Protect the Eureka dashboard and API using spring-boot-starter-security Basic Auth.
  • CSRF:
    • Since Eureka clients send POST requests for heartbeats, we must disable CSRF for the Eureka client-registration endpoint /eureka/**, or the Eureka clients will fail to register.
@Bean
public SecurityFilterChain filterChain(HttpSecurity http) throws Exception {
    http.csrf(csrf -> csrf.ignoringRequestMatchers("/eureka/**"));
    return http.build();
}

If you protect your server with Spring Security, you must include this configuration on the Server side, or your clients will receive 403 Forbidden errors:

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

Alternatives to Eureka

While Eureka is excellent for Spring-native environments due to its “Eventual Consistency” (high availability) model, other tools prioritize data integrity or native platform integration.

FeatureNetflix EurekaHashiCorp ConsulApache ZookeeperKubernetes (K8s)
Best Use CaseSpring Cloud Java apps.Multi-datacenter & Service Mesh.Large-scale Apache clusters (Kafka/Hadoop).Native container orchestration.
CAP TheoremAP (Availability Focus)CP (Consistency Focus)CP (Consistency Focus)CP (via etcd)
Health CheckClient-side Heartbeats.Multi-level (Agent, HTTP, TCP).Ephemeral Nodes (Session-based).Liveness/Readiness Probes.
Built-in Key/ValueNo (needs Spring Config).Yes (Native).Yes (Hierarchical).Yes (ConfigMaps/Secrets).
Discovery ViaREST API / Client Lib.DNS / HTTP API.Client Library (Curator).Internal DNS / Environment Vars.

Which one to choose ?

ProviderPick this ifWhy
HashiCorp ConsulYou have a polyglot env. (eg. some services in Go, some in Python, some in Java) or need to connect services across different data centers.It’s easy to use DNS interface, makes it compatible even for legacy applications to find a service using a standard URL like my-service.service.consul.
ZookeeperYou are already using the Hadoop ecosystem eg. Kafka, Hadoop, or HBase.It is a battle-tested coordination service. However, it is “thick” and difficult to maintain. Unless you already have a Zookeeper cluster, it is usually overkill for simple microservice discovery.
Kubernetes ServicesYour entire stack is in Kubernetes (K8s).K8s has built-in service discovery. It uses internal CoreDNS and kube-proxy to handle discovery, load balancing and route-traffic at the network level.

Insight:
→ Adding Eureka on top of Kubernetes is often redundant and adds an “extra hop” to your network requests. —

The Eureka Lifecycle

The following table summarizes the core role of a Naming Server within the architecture.

PhaseDescriptionDefault Interval
RegistrationService sends its IP/Port and Metadata upon startup.Once at Startup
HeartbeatService sends a “renew” signal to prove it is still alive.Every 30s
EvictionEureka removes services that haven’t checked in recently.90s (Lease Expiry)
Client-side CacheClients (Microservices) cache the registry locally for faster lookups.Every 30s

Security and Authentication

Eureka Server primarily relies on standard web security protocols rather than having a proprietary authentication engine, because it is usually deployed within a private network, security is often layered.

Here is a breakdown of the authentication mechanisms and the best practices for securing your Eureka cluster in a PROD environment.

Critical:
→ While embedding credentials in the Eureka Serverservice-url is the quickest way to get started, it creates a security risk by exposing passwords in plain text within configuration files or environment variables.

Basic authentication (Default)

Eureka supports standard HTTP Basic Auth. The client sends an Authorization header with every request.

Best Practice:
→ Even with Basic Auth enabled, never expose the Eureka server to the public internet.

  • Server side:
    • Add spring-boot-starter-security to the server to enables authentication.
    • Also configure a SecurityFilterChain to disable CSRF for /eureka/** (otherwise, heartbeats will fail).
  • Client Setup:
    • The credentials are embedded in the service-url.defaultZone property for the Eureka server url.
    • Syntax: http://user:password@eureka-host:8761/eureka/.

Mutual TLS (mTLS) / Client certificates

For higher security, enforce X.509 certificates. This ensures that not only does the client trust the server, but the server also validates the client’s identity via a digital certificate.

Provides much stronger security ensuring that only trusted servers/machines can join the registry and prevents “Man-in-the-Middle” attacks.

In this mechanism, both the server and the client must have a valid trust-store and key-store.

  • Application config:
    • Requires setting server.ssl.client-auth=need on the Eureka Server.
    • Set eureka.client.tls.enabled: true and provide the key-store and trust-store paths on the Eureka Client.

Form-based login (Dashboard only)

While the API uses Basic Auth, the Eureka Dashboard (the UI) can be protected with a standard form-based login for human administrators. It’s used strictly for browser-based access to view registered instances.

This requires to update Spring Security configuration to allow HTTP Basic for API calls (from microservices) while using Form Login for the UI.


IP whitelisting (Network Level)

While not an “authentication” protocol in the traditional sense, it is a standard practice to restrict access to the Eureka server at the network level.

This mechanism requires configuring the firewall or Security Groups (in AWS/Azure) to only allow traffic from the CIDR range of the microservices.