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:portof their dependencies.
- Services no longer need to know the specific
- 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
| Property | Description |
|---|---|
| register-with-eureka | Set to false so the server doesn’t appear in its own list of available services. |
| fetch-registry | Set to false because the server is the primary source of truth and doesn’t need to pull data. |
| server.port | The 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:
| Setting | Recommendation | Why? |
|---|---|---|
| Prefer IP Address | eureka.instance.prefer-ip-address: true | Useful in containerized environments (Docker/K8s) where hostnames can be volatile. |
| Sync Strategy | eureka.server.registry-sync-retries | Increase this value to ensure a booting server tries harder to pull the registry from its peers before timing out. |
| Self-Preservation | eureka.server.enable-self-preservation | Keep this enabled (default) in production to prevent mass-deregistration during network flickers. |
| Wait for Peers | eureka.server.wait-time-in-ms-when-sync-empty | Set 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://
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.
| Feature | Netflix Eureka | HashiCorp Consul | Apache Zookeeper | Kubernetes (K8s) |
|---|---|---|---|---|
| Best Use Case | Spring Cloud Java apps. | Multi-datacenter & Service Mesh. | Large-scale Apache clusters (Kafka/Hadoop). | Native container orchestration. |
| CAP Theorem | AP (Availability Focus) | CP (Consistency Focus) | CP (Consistency Focus) | CP (via etcd) |
| Health Check | Client-side Heartbeats. | Multi-level (Agent, HTTP, TCP). | Ephemeral Nodes (Session-based). | Liveness/Readiness Probes. |
| Built-in Key/Value | No (needs Spring Config). | Yes (Native). | Yes (Hierarchical). | Yes (ConfigMaps/Secrets). |
| Discovery Via | REST API / Client Lib. | DNS / HTTP API. | Client Library (Curator). | Internal DNS / Environment Vars. |
Which one to choose ?
| Provider | Pick this if | Why |
|---|---|---|
| HashiCorp Consul | You 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. |
| Zookeeper | You 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 Services | Your 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.
| Phase | Description | Default Interval |
|---|---|---|
| Registration | Service sends its IP/Port and Metadata upon startup. | Once at Startup |
| Heartbeat | Service sends a “renew” signal to prove it is still alive. | Every 30s |
| Eviction | Eureka removes services that haven’t checked in recently. | 90s (Lease Expiry) |
| Client-side Cache | Clients (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-urlis 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-securityto the server to enables authentication. - Also configure a
SecurityFilterChainto disable CSRF for/eureka/**(otherwise, heartbeats will fail).
- Add
- Client Setup:
- The credentials are embedded in the
service-url.defaultZoneproperty for the Eureka server url. - Syntax: http://user:password@eureka-host:8761/eureka/.
- The credentials are embedded in the
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=needon the Eureka Server. - Set
eureka.client.tls.enabled: trueand provide thekey-storeandtrust-storepaths on the Eureka Client.
- Requires setting
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.