Microservices Intro + Spring Cloud Config/Eureka
- What is a microservice architecture? Benefits vs monolith?
- Main challenges of microservices (distributed systems, data consistency, communication, deployment)?
- What is Spring Cloud? Why use it with Spring Boot?
- Spring Cloud Config Server – purpose (centralized config management)?
- How Config Server works with Git backend?
- Config Client – how to fetch config from Config Server?
- Spring Cloud Eureka – service registry & discovery?
- Eureka Server setup steps?
- Eureka Client registration (@EnableDiscoveryClient)?
- Difference between Config Server vs application.properties?
- Refresh config at runtime with @RefreshScope?
- Best practices for microservices config management?
- Eureka self-preservation mode – what is it and when it activates?
- When to use Config Server vs external tools (Consul, Vault)?
- How does Eureka handle service discovery and load balancing?
What is a microservice architecture? Benefits vs monolith?
=> Microservice architecture (also called microservices) is a design approach where a large application is built as a collection of small, independent services that each perform a single business function, communicate over a network (usually HTTP/REST or messaging), and can be developed, deployed, scaled, and maintained independently.
=> Each microservice has its own codebase, database, deployment of pipeline, team (often)
=> Monolithic architecture (traditional) is the opposite: one single, large application with all components tightly coupled in one codebase, one database, and deployed as one unit.
Benefits of Microservices (vs Monolith)
=> One service crash doesn't take down the whole app
=> Change one service without touching others
=> Teams own their service end-to-end (dev, test, deploy, monitor)
=> Scale only the busy services (e.g., payment service during sales) — cost-efficient
=> Independent deploy of single service
=> Different tech per service (Java, Python, Node.js, etc.)
Microservices vs Monolith
| Aspect | Monolithic Architecture | Microservice Architecture | Winner (in most cases) |
|---|---|---|---|
| Structure | Single codebase, single deployable unit | Many small, independent services | Microservices (flexibility) |
| Development speed | Fast initially, slows down as app grows | Slower initially, faster at scale | Microservices (long-term) |
| Scalability | Scale entire app (vertical or horizontal) | Scale individual services independently | Microservices |
| Technology choice | One tech stack for whole app | Different tech per service (Java, Python, Node.js, etc.) | Microservices |
| Fault isolation | One failure can crash entire app | Failure in one service usually isolated | Microservices |
| Deployment | Full redeploy for any change | Independent deploy of single service | Microservices |
| Team structure | Large team on one codebase | Small, autonomous teams per service | Microservices |
| Complexity | Simple at small scale | High complexity (network, distributed tracing, etc.) | Monolith (early stage) |
| Database | Single shared DB | Database per service (polyglot persistence) | Microservices |
| Testing | Easier unit tests, harder end-to-end | Harder integration, easier individual service tests | Depends on scale |
| Performance overhead | Low (in-process calls) | Higher (network calls, serialization) | Monolith |
| Maintenance | Becomes nightmare as code grows | Easier to maintain individual services | Microservices (long-term) |
Main challenges of microservices (distributed systems, data consistency, communication, deployment)?
1. Distributed Systems Complexity
=> Services run on separate machines, often across multiple servers, data centers, or cloud regions
=> Calls between services go over the network (HTTP, gRPC, messaging). Networks can fail, timeout. Circuits breakers (Resilence4j) can be the solution.
=> One service can be down/slow while others are healthy. This results in cascading failures if not handled. We can try Timeouts and retries with backoff for distributed systems/communication.
=> Hard to trace single user request across 10 services. We need distributed tracing tools like Zipkin, Jaeger, OpenTelemetry
=> Different servers have slightly different clocks i.e problems with timestamp, event ordering. We need to use Service mesh (Istio, Linkerd).
=> Basically Service Mesh is used for distributed complexity + communication + deployment (not just clock skew)
2. Data consistency (The hardest problem)
=> Cannot use traditional 2 phase commit (too slow, locks everything)
=> Data can be temporarily inconsistent across services i.e eventual consistency instead of immediate
=> Long running transactions split into local transactions + compensating actions. (Eg. Order placed -> Payment failed -> rollback inventory) i.e Saga pattern (orchestrated or choreographed) needed
=> Querying across services : Cannot do simple SQL joins. We need API composition/BFF or CQRS views
3. Inter service communication
=> Services must talk with each other in either of the following ways
- Synchronous (HTTP/REST, gRPC)
- Asynchronous (messaging)
=> Synchronous calls can cause cascading failures i.e one slow service slows everything
=> How does Service A finds Service B's IP/port ? So we need Service Discovery (Eureka, Kubernetes DNS, Consul), API gateway (Spring cloud gateway)
=> Distribute traffic across multiple instances of the same service i.e load balancing. We can use Spring Cloud load balancer
=> Versioning & backward compatibility : Changing one service should not break other
=> Security : Authenticate/Authorize calls between services (OAuth, JWT)
=> For synchronous communication issues, prefer asynchronous messaging (Kafka, RabbitMQ) for loose coupling
4. Deployment & Operations Complexity
=> Deploying 1 monolith is simple. Deploying 10–100 microservices is hard.
=> We need to deploy and monitor many services. So, we need CI/CD (Jenkins) pipelines per service
=> How to manage config for these many services ? We can use Spring Cloud config, Kubernetes ConfigMaps, Consul
=> We need Centralized logging/tracing/metrics (We can use Zipkin)
=> Logs scattered across services, need correlation IDs
=> Service mesh (Istio, Linkerd) for traffic management, observability
NOTE :
What is gRPC ?
=> gRPC is a modern, high-performance open-source RPC (Remote Procedure Call) framework
| Feature | gRPC | Traditional REST (JSON/HTTP) |
|---|---|---|
| Protocol | HTTP/2 (binary) | HTTP/1.1 or HTTP/2 (text-based) |
| Data Format | Protocol Buffers (binary, compact) | JSON (text, larger) |
| Performance | Very high (faster, lower latency) | Slower (more overhead) |
| Contract | .proto file (strongly typed) | OpenAPI/Swagger (optional) |
| Streaming | Yes (unary, server, client, bidirectional) | Limited (only server-sent events) |
| Language Support | 10+ languages (Java, Go, Python, C++, etc.) | Mostly language-agnostic via HTTP |
| Typical Use Case | Internal microservices communication | Public APIs, browser/mobile clients |
What is Spring Cloud? Why use it with Spring Boot?
=> Spring Cloud is a framework that provides tools and patterns to build and manage distributed systems and microservices on top of Spring Boot.
=> It simplifies common challenges in cloud-native and microservices architectures, such as configuration management, service discovery, load balancing, fault tolerance, API gateways, and more.
=> Spring Cloud is not a single tool. Spring Cloud is a collection of independent Spring projects (each solving one microservices problem). You add only the ones you need as dependencies.
Main Components (Most Commonly Used)
- Spring Cloud Config
- Spring Cloud Netflix Eureka
- Spring Cloud Gateway
- Spring Cloud OpenFeign
- Spring Cloud LoadBalancer
- Spring Cloud Circuit Breaker / Resilence4j
- Spring Cloud Sleuth + Zipkin
| Component | Purpose | Popular Tools / Alternatives |
|---|---|---|
| Spring Cloud Config | Centralized configuration management (external config for all services) | Git, Vault, Consul |
| Spring Cloud Netflix Eureka | Service registry & discovery (services register themselves, clients find them) | Consul, Kubernetes DNS |
| Spring Cloud Gateway | API Gateway (routing, load balancing, security, rate limiting) | Kong, Zuul (older) |
| Spring Cloud OpenFeign | Declarative HTTP client (simpler than RestTemplate) | WebClient, RestTemplate |
| Spring Cloud LoadBalancer | Client-side load balancing | Ribbon (older) |
| Resilience4j / Spring Cloud Circuit Breaker | Fault tolerance (circuit breaker, retry, rate limiter, bulkhead) | Hystrix (deprecated) |
| Spring Cloud Sleuth + Zipkin | Distributed tracing (track requests across services) | OpenTelemetry, Jaeger |
Why Use Spring Cloud with Spring Boot?
| Scenario | Spring Boot Alone | Spring Boot + Spring Cloud |
|---|---|---|
| Configuration | application.properties per service | Centralized config via Config Server + Git |
| Service discovery | Hardcoded URLs or manual config | Eureka/Consul — services auto-register & discover |
| Load balancing | Manual or external LB | Client-side LB (Spring Cloud LoadBalancer) |
| Fault tolerance | Manual try-catch/retries | Resilience4j circuit breaker + retry automatically |
| API Gateway | No built-in | Spring Cloud Gateway for routing/security |
| Tracing across services | Hard (manual correlation IDs) | Sleuth + Zipkin/OpenTelemetry auto-tracing |
Spring Cloud Config Server – purpose (centralized config management)?
=> Spring Cloud Config Server is a centralized configuration server that stores properties externally (usually in GIT) and serves them to client microservices on startup.
=> Spring Cloud Config Server allows you to store and manage configuration properties for all of your microservices in one place instead of scattering them across each service's application.properties files
=> So the core purpose is centralized configuration management
Spring Cloud Config Server centralizes everything in an external backend (usually Git), so:
=> All services fetch config from one source at startup
=> Change config in Git → services can refresh without redeploy
=> Environment-specific config (dev, test, prod) is handled cleanly
=> Sensitive data can be encrypted or stored securely
=> Version control for config changes (audit trail via Git)
How It Works (Core Flow)
1. Config Server — a standalone Spring Boot app
=> You run it on its own port (default 8888)
=> It connects to a backend (most common: Git repository)
=> Git repo contains config files like:
application.yml (default for all apps)
employee-service-dev.yml (dev profile for employee-service)
payment-service-prod.yml (prod profile for payment-service)
2. Config Client — each microservice
=> Add dependency: spring-cloud-starter-config
=> In bootstrap.yml (not application.yml) :
spring:
cloud:
config:
uri: http://localhost:8888 # Config Server URL
application:
name: employee-service
profiles:
active: dev
=> On startup, the service asks Config Server:
"Give me config for employee-service-dev"
=> Config Server reads Git → returns properties → service applies them
3. Dynamic Refresh (no restart needed)
=> Add @RefreshScope to beans using @Value("${my.property}")
=> After changing config in Git, call /actuator/refresh (POST) on the client → properties reload
Benefits (Why It's Powerful)
=> Single source of truth → change once in Git, all services get update
=> Environment separation → dev uses H2, prod uses PostgreSQL — no code change
=> Security → encrypt sensitive values or use Vault integration
=> Version control → all config changes tracked in Git
=> No redeploy for config changes (with refresh)
=> Rollback → revert Git commit to roll back config
How Config Server works with Git backend?
=> Spring Cloud Config Server uses Git as its primary backend to store and serve configuration files for microservices (or any Spring Boot apps).
=> This makes configuration centralized, version-controlled, and easy to manage without redeploying services.
Step-by-Step Flow (How It Works)
1. Config Server Setup
=> You create a separate Spring Boot application (Config Server)
=> Add dependency: spring-cloud-config-server
=> Enable with @EnableConfigServer on the main class
=> Configure Git in application.yml (or properties):
server:
port: 8888
spring:
cloud:
config:
server:
git:
uri: https://github.com/yourusername/config-repo.git # Your Git repo URL
# Optional: username/password or SSH key for private repo
search-paths: '{application}' # Looks for app-specific files
default-label: main # Branch name
2. Git Repository Structure (Backend)
=> You create a Git repo (e.g., config-repo on GitHub) with configuration files
=> Naming convention (most common):
config-repo/
├── application.yml # Global defaults
├── employee-service.yml # employee-service defaults
├── employee-service-dev.yml # Dev profile overrides
└── payment-service-prod.yml # Prod profile overrides
3. Config Client (Each Microservice)
=> Add dependency: spring-cloud-starter-config
=> Use bootstrap.yml (not application.yml — loaded first):
spring:
application:
name: employee-service # Must match Git file name
profiles:
active: dev # Or set via --spring.profiles.active=dev
cloud:
config:
uri: http://localhost:8888 # Config Server URL
fail-fast: true # Fail if Config Server unavailable
4. Startup Sequence
=> Microservice starts → reads bootstrap.yml → connects to Config Server (http://localhost:8888).
=> Requests config for: employee-service-dev (name + profile).
=> Config Server:
Clones/pulls latest Git repo.
Searches for matching files (employee-service-dev.yml, employee-service.yml, application-dev.yml, application.yml).
Merges properties (profile-specific overrides default).
Returns combined config as YAML/JSON.
=> Client applies properties → beans are created with these values.
5. Dynamic Refresh (No Restart Needed)
=> Change config in Git → commit/push.
=> curl -X POST http://localhost:8080/actuator/refresh
=> Beans with @RefreshScope reload new values instantly.
Config Client – how to fetch config from Config Server?
=> Spring Cloud Config Client is the part of Spring Cloud that enables any Spring Boot application (microservice or monolith) to fetch its configuration dynamically from the Config Server at startup (and optionally refresh at runtime)
How Config Client Fetches Config from Config Server (Step-by-Step)
1. Add Dependency (in the client service's pom.xml)
<dependency>
<groupId>org.springframework.cloud</groupId>
<artifactId>spring-cloud-starter-config</artifactId>
</dependency>
2. Use bootstrap.yml (or bootstrap.properties) – Very Important
=> Config Client uses bootstrap file (loaded beforeapplication.yml)
=> It tells the app: "Go to Config Server to get my config".
=> Example bootstrap.yml (recommended):
spring:
application:
name: employee-service # Must match the file name in Git (employee-service-*.yml)
profiles:
active: dev # dev, test, prod – matches profile in Config Server
cloud:
config:
uri: http://localhost:8888 # Config Server URL
fail-fast: true # Fail startup if Config Server unavailable
# Optional: username/password for auth
# username: user
# password: ${CONFIG_SERVER_PASSWORD}
=> spring.application.name + spring.profiles.active → tells Config Server which file to load (e.g., employee-service-dev.yml).
=> spring.cloud.config.uri → points to Config Server.
3. Startup Sequence
=> Client app starts → reads bootstrap.yml
=> Connects to Config Server (http://localhost:8888)
=> Requests: "Give me config for employee-service-dev".
=> Config Server:
Pulls latest from Git.
Finds matching files (e.g., employee-service-dev.yml, application-dev.yml, application.yml).
Merges them (profile-specific overrides default).
Returns combined properties as YAML/JSON.
=> Client receives config → overrides local application.yml → beans are created with these values.
4. Dynamic Refresh (Optional – No Restart Needed)
=> Enable Actuator refresh endpoint:
management.endpoints.web.exposure.include=refresh
=> Annotate beans with @RefreshScope:
@Value("${my.feature.toggle}")
private boolean featureToggle;
@RefreshScope // This bean reloads on /refresh
@Component
public class FeatureToggleService { ... }
=> After changing config in Git → push → call:
curl -X POST http://localhost:8080/actuator/refresh
=> Properties reload instantly.
Key Points & Best Practices
=> bootstrap.yml is loaded before the main context — that's why config is fetched early.
=> fail-fast: true → app fails to start if Config Server is down (fail-fast is safer than using stale local config).
=> Use Git as backend → version control, audit trail, easy branching for environments.
=> Security → use HTTPS + basic auth or OAuth on Config Server.
=> Profiles → spring.profiles.active=dev,test → merges multiple profiles.
Spring Cloud Eureka – service registry & discovery?
=> Spring Cloud Netflix Eureka Server is a service registry and discovery solution provided by Spring Cloud (built on top of Netflix Eureka).
=> It allows microservices to register themselves and discover other services dynamically, without hardcoding URLs or IP addresses
What is Service Registry & Discovery?
=> In microservices, services run on different machines/instances and their locations (IP/port) can change (due to scaling, failures, deployments).
=> Service Registry: A central place where services register their location (IP, port, health).
=> Service Discovery: Other services query the registry to find available instances of a target service (e.g., "Where is payment-service?").
=> Eureka solves this by acting as a highly available, distributed registry.
How Eureka Works (Core Components & Flow)
1. Eureka Server (Registry)
=> A standalone Spring Boot app.
=> Services register with it.
=> Clients query it for service locations.
=> Runs on default port 8761.
=> Highly available (can run multiple instances that sync with each other).
2. Eureka Client (Each Microservice)
=> Add dependency: spring-cloud-starter-netflix-eureka-client
=> Enable with @EnableDiscoveryClient (or @EnableEurekaClient).
=> In application.yml:
eureka:
client:
service-url:
defaultZone: http://localhost:8761/eureka/
spring:
application:
name: employee-service
3. Registration Flow
=> Service starts → sends heartbeat every 30 seconds to Eureka Server ("I'm alive at http://192.168.1.10:8080")
=> Eureka Server stores: service name, instance ID, IP, port, health
=> If no heartbeat for ~90 seconds → instance marked DOWN and removed
4. Discovery Flow
=> Service A needs Service B → asks Eureka: "Give me all instances of payment-service".
=> Eureka returns list of healthy instances (IP:port).
=> Service A uses client-side load balancer (e.g., Spring Cloud LoadBalancer) to pick one and call it.
5. Eureka Dashboard
=> http://localhost:8761 → shows registered services, status (UP/DOWN), instances.
Eureka Self-preservation mode
=> If many heartbeats miss (network partition), Eureka stops removing instances to avoid false DOWN
Eureka Server setup steps?
Explained the steps with example
Step 1: Create a New Spring Boot Project for Eureka Server
=> Use https://start.spring.io or IntelliJ Spring Initializr.
=> Project: Maven / Gradle
=> Language: Java 17 or 21 (or 25)
=> Spring Boot: Latest stable (3.5.x or 4.x)
=>. Dependencies :
Spring Boot Actuator (optional but recommended)
Spring Cloud Netflix Eureka Server
=> Enter Group and Artifact
=> Generate → import in IntelliJ
Step 2: Add Dependency in pom.xml (if not added automatically)
<dependency>
<groupId>org.springframework.cloud</groupId>
<artifactId>spring-cloud-starter-netflix-eureka-server</artifactId>
</dependency>
Step 3: Enable Eureka Server in Main Class
Use the annotation @EnableEurekaServer on top of main class
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 enables the Eureka Server
public class EurekaServerApplication {
public static void main(String[] args) {
SpringApplication.run(EurekaServerApplication.class, args);
}
}
Step 4: Configure application.yml (or properties)
server:
port: 8761 # Default Eureka port (can be any, but 8761 is standard)
spring:
application:
name: eureka-server
eureka:
client:
register-with-eureka: false # Eureka Server does NOT register itself
fetch-registry: false # No need to fetch registry (it's the registry)
service-url:
defaultZone: http://localhost:8761/eureka/ # Self-reference
instance:
hostname: localhost
server:
enable-self-preservation: false # Disable in dev (prevents false DOWN status)
Step 5: Disable Security (Development Only)
=> By default, Eureka has basic security — disable for local testing:
management.security.enabled=false
=> In production: enable security (basic auth, JWT, etc.).
Step 6: Run & Verify
=> Run the app → Eureka Server starts on http://localhost:8761
=> Open browser: http://localhost:8761
=> You should see the Eureka Dashboard
Instances currently registered → empty at first
System status → DS replica (shows if HA is configured)
Environment, config, etc.
Step 7: Register a Client Service (Quick Test)
Create a simple client app (e.g., employee-service):
=> Add dependency: spring-cloud-starter-netflix-eureka-client
=> Add annotation: @EnableDiscoveryClient or @EnableEurekaClient on main class
=> In application.yml:
eureka:
client:
service-url:
defaultZone: http://localhost:8761/eureka/
spring:
application:
name: employee-service
=> Run client → refresh Eureka dashboard → see "EMPLOYEE-SERVICE" registered with status UP
Eureka Client registration (@EnableDiscoveryClient)?
@EnableDiscoveryClient is a Spring annotation that activates service discovery client features in your application. It tells Spring Cloud to:
=> Register the current service with the Eureka Server (or other discovery servers)
=> Enable the service to query the registry for other services' locations (IP/port)
=> Periodically send heartbeats to Eureka to stay registered and healthy
NOTE
=> We can use either @EnableDiscoveryClient or @EnableEurekaClient
=> Recommended to use @EnableDiscoveryClient (generic) instead of @EnableEurekaClient (Eureka-specific)
Step-by-Step: How Eureka Client Registration Works
1. Add Dependency in pom.xml (microservice)
<dependency>
<groupId>org.springframework.cloud</groupId>
<artifactId>spring-cloud-starter-netflix-eureka-client</artifactId>
</dependency>
2. Add the annotation @EnableDiscoveryClient or @EnableEurekaClient on top of main class
@SpringBootApplication
@EnableDiscoveryClient // This is the key line
public class EmployeeServiceApplication {
public static void main(String[] args) {
SpringApplication.run(EmployeeServiceApplication.class, args);
}
}
=> @EnableDiscoveryClient is the generic annotation (works with Eureka, Consul, Zookeeper, Kubernetes, etc.)
=> Alternative: @EnableEurekaClient (specific to Eureka, older but still works)
3. Configure in application.yml / bootstrap.yml
=> spring:
application:
name: employee-service # Unique service name (used in registry)
eureka:
client:
service-url:
defaultZone: http://localhost:8761/eureka/ # Eureka Server URL
register-with-eureka: true
fetch-registry: true
instance:
prefer-ip-address: true # Register with IP instead of hostname (better in containers)
lease-renewal-interval-in-seconds: 30 # Heartbeat every 30s
lease-expiration-duration-in-seconds: 90 # Remove if no heartbeat for 90s
4. Registration Flow (What Happens at Startup)
=> App starts → reads Eureka config
=> @EnableDiscoveryClient triggers EurekaClient bean creation.
=> Service sends registration request to Eureka Server (http://localhost:8761/eureka/apps/employee-service)
=> Eureka Server adds it to registry with Service name, Instance details : IP, port, health, metadata
=> Service starts sending heartbeats every 30 seconds (default)
=> Eureka dashboard shows "EMPLOYEE-SERVICE" as UP
5. Discovery Flow (How Other Services Find It)
=> Another service (e.g., Payment Service) wants to call employee-service.
=> It asks Eureka: "Give me instances of employee-service".
=> Eureka returns list of healthy instances (e.g., http://192.168.1.10:8080)
=> Client uses load balancer (Spring Cloud LoadBalancer) to pick one and call it
6. Health Check
=> Eureka periodically calls the service's /actuator/health (if Actuator is enabled)
=> If health is DOWN → instance marked DOWN in registry
Best practices
=> Use @EnableDiscoveryClient (generic) instead of @EnableEurekaClient (Eureka-specific)
=> Set spring.application.name — must be unique and match across environments
=> Use prefer-ip-address: true — especially in Docker/Kubernetes
=> Enable Actuator health for accurate status
Difference between Config Server vs application.properties?
application.properties / yml
=> It is the default, local configuration mechanism in Spring Boot.
=> It is simple, built-in, and sufficient for small apps or monoliths.
=> Config is bundled with the JAR, so changes require redeploy.
=> Hard to secure sensitive config (in JAR or repo)
Spring Cloud Config Server
=> It is an external, centralized configuration server for microservices.
=> It pulls config from Git (or other backends), serves it to clients, and supports runtime refresh.
=> Ideal for large-scale systems where config needs to be managed centrally and updated without redeploy.
=> Easy to secure sensitive config (encryption, Vault)
| Aspect | application.properties / application.yml | Spring Cloud Config Server | Winner (in which scenario) |
|---|---|---|---|
| Location of config | Inside the application JAR/WAR (bundled with code) | External (usually Git repo, Vault, database, file system) | Config Server (centralized) |
| Centralized? | No — each service has its own config file | Yes — single source of truth for all services | Config Server |
| Change config without redeploy | No — requires rebuild & redeploy of the app | Yes — change in Git → refresh via /actuator/refresh | Config Server |
| Environment-specific config | Separate files (application-dev.properties, etc.) | Same file with profile suffix (employee-service-dev.yml) | Both good, Config Server more scalable |
| Version control | Difficult (config in code repo, but often ignored) | Full Git history, audit trail, rollback easy | Config Server |
| Security / Sensitive data | Hard to secure (in JAR or repo) | Can encrypt values, integrate Vault, external secrets | Config Server |
| Refresh at runtime | No (restart needed) | Yes — with @RefreshScope + /actuator/refresh | Config Server |
| Use case | Simple apps, monoliths, local development | Microservices, cloud-native, multiple environments | Config Server for scale |
| Setup complexity | Zero (built-in) | Medium (separate server, Git setup, client config) | application.properties |
| Scalability | Poor for 10–100 services (update all manually) | Excellent (change once → all services get it) | Config Server |
| Fallback | Local file always available | Fallback to local config if Config Server down (fail-fast option) | Both |
=> @RefreshScope is a Spring Cloud annotation that allows a bean to reload its configuration properties at runtime without restarting the entire application
How @RefreshScope Works
=> When a Spring Boot application uses Spring Cloud Config, configuration is fetched from an external source (usually Git via Config Server) at startup.
=> Normally, changing config in Git requires restarting the app to pick up new values.
=> @RefreshScope solves this by making certain beans refreshable:
1. Mark the bean with @RefreshScope
@Component
@RefreshScope
public class FeatureToggleService {
@Value("${feature.payment.enabled:false}")
private boolean paymentEnabled;
public boolean isPaymentEnabled() {
return paymentEnabled;
}
}
=> @RefreshScope tells Spring: "This bean's properties can be reloaded."
2. Change config in Git
=> Update Git file (e.g., employee-service-dev.yml):
feature:
payment:
enabled: true
=>.Commit & push to Git.
3. Trigger Refresh
=> Expose the refresh endpoint (in application.properties):
management.endpoints.web.exposure.include=refresh
=> Call the endpoint (POST request) from microservice : (or via postman)
curl -X POST http://localhost:8080/actuator/refresh
4. What Happens During Refresh
=> Spring Cloud Config Client detects the refresh request.
=> Re-fetches latest config from Config Server.
=> Destroys and recreates all beans annotated with @RefreshScope.
=> New values are injected into @Value fields.
=> No full application restart — only affected beans are refreshed.
Key Points & Best Practices
=> Scope: Only beans with @RefreshScope are refreshed — not the entire context.
=> @Value: Works only on fields annotated with @Value inside @RefreshScope beans.
=> Not for all beans — don't put it on controllers/services that hold state (e.g., caches, thread pools) — can cause issues.
=> Safe for: Configuration classes, feature toggles, property-based services.
=> Actuator required: /actuator/refresh must be exposed (security: protect in prod).
=> Alternative: Manual refresh via RefreshEndpoint bean (rare).
Eureka self-preservation mode – what is it and when it activates?
=> In normal operation, Eureka expects every registered service instance to send a heartbeat every 30 seconds (default).
=> If Eureka doesn't receive a heartbeat for ~90 seconds (3 missed heartbeats), it removes the instance from the registry and marks it as DOWN.
=> Self-preservation mode overrides this aggressive eviction when Eureka detects that too many instances are suddenly missing heartbeats.
=> Instead of removing them (which could cause cascading failures), Eureka stops removing instances and enters a protective state.
In this Eureka self-preservation mode:
=> Eureka assumes the problem is not with the instances, but with the network or Eureka itself.
=> It continues to serve the last known healthy registry.
=> It logs a message like:
EMERGENCY! EUREKA MAY BE INCORRECTLY CLAIMING INSTANCES ARE UP WHEN THEY'RE NOT. RENEWALS ARE LESSER THAN THE THRESHOLD AND HENCE THE INSTANCES ARE NOT BEING EXPIRED JUST TO BE SAFE.
When Does Self-Preservation Mode Activate?
=> Eureka enters self-preservation mode when the renewal percent threshold is not met
=> Default threshold: 85% of expected heartbeats must arrive in a sliding window (default 15 minutes).
=> If actual renewals fall below 85% → self-preservation activates.
=> Common triggers:
Network partition / outage between clients and Eureka
High network latency or packet loss
Many clients restarting or redeploying simultaneously
Eureka Server itself under heavy load
Sudden spike in instance count (scaling event)
How to Identify It’s Active?
=> Eureka dashboard shows:
RENEWAL THRESHOLD NOT MET
EMERGENCY! EUREKA MAY BE INCORRECTLY CLAIMING INSTANCES ARE UP...
=> Logs show similar warnings.
How to Control / Disable It?
In development (recommended):
eureka:
server:
enable-self-preservation: false
In production:
=> Keep it enabled (default = true) — it protects against false positives.
=> Tune threshold if needed:
eureka:
server:
renewal-percent-threshold: 0.85 # default 85%
eviction-interval-timer-in-ms: 60000 # check every 60s
When to use Config Server vs external tools (Consul, Vault)?
=> Use Spring Cloud Config Server when you're in Spring Boot ecosystem, need simple Git-based config, runtime refresh, and centralized properties.
=> Use Consul for combined service discovery + config, multi-DC, or non-Java services
=> Use Vault for strong secret management, encryption, dynamic credentials, audit, and compliance
=> In Kubernetes, prefer native ConfigMaps/Secrets for simplicity
How does Eureka handle service discovery and load balancing?
A. Service Discovery in Eureka
@EnableDiscoveryClient is a Spring annotation that activates service discovery client features in your application. It tells Spring Cloud to:
=> Register the current service with the Eureka Server (or other discovery servers)
=> Enable the service to query the registry for other services' locations (IP/port)
=> Periodically send heartbeats to Eureka to stay registered and healthy
NOTE
=> We can use either @EnableDiscoveryClient or @EnableEurekaClient
=> Recommended to use @EnableDiscoveryClient (generic) instead of @EnableEurekaClient (Eureka-specific)
Step-by-Step: How Eureka Client Registration Works
1. Add Dependency in pom.xml (microservice)
<dependency>
<groupId>org.springframework.cloud</groupId>
<artifactId>spring-cloud-starter-netflix-eureka-client</artifactId>
</dependency>
2. Add the annotation @EnableDiscoveryClient or @EnableEurekaClient on top of main class
@SpringBootApplication
@EnableDiscoveryClient // This is the key line
public class EmployeeServiceApplication {
public static void main(String[] args) {
SpringApplication.run(EmployeeServiceApplication.class, args);
}
}
=> @EnableDiscoveryClient is the generic annotation (works with Eureka, Consul, Zookeeper, Kubernetes, etc.)
=> Alternative: @EnableEurekaClient (specific to Eureka, older but still works)
3. Configure in application.yml / bootstrap.yml
=> spring:
application:
name: employee-service # Unique service name (used in registry)
eureka:
client:
service-url:
defaultZone: http://localhost:8761/eureka/ # Eureka Server URL
register-with-eureka: true
fetch-registry: true
instance:
prefer-ip-address: true # Register with IP instead of hostname (better in containers)
lease-renewal-interval-in-seconds: 30 # Heartbeat every 30s
lease-expiration-duration-in-seconds: 90 # Remove if no heartbeat for 90s
4. Registration Flow (What Happens at Startup)
=> App starts → reads Eureka config
=> @EnableDiscoveryClient triggers EurekaClient bean creation.
=> Service sends registration request to Eureka Server (http://localhost:8761/eureka/apps/employee-service)
=> Eureka Server adds it to registry with Service name, Instance details : IP, port, health, metadata
=> Service starts sending heartbeats every 30 seconds (default)
=> Eureka dashboard shows "EMPLOYEE-SERVICE" as UP
5. Discovery Flow (How Other Services Find It)
=> Another service (e.g., Payment Service) wants to call employee-service.
=> It asks Eureka: "Give me instances of employee-service".
=> Eureka returns list of healthy instances (e.g., http://192.168.1.10:8080)
=> Client uses load balancer (Spring Cloud LoadBalancer) to pick one and call it
6. Health Check
=> Eureka periodically calls the service's /actuator/health (if Actuator is enabled)
=> If health is DOWN → instance marked DOWN in registry
B. Load Balancing in Eureka
=> Eureka provides client-side load balancing
=> Eureka itself does not perform server-side load balancing
How Load Balancing Works
1. Client-side Load Balancing (most common in Spring Cloud)
=> When a client calls another service, it gets the list of instances from Eureka
=> Spring Cloud uses a load balancer client to pick one instance
=> Default load balancer: Spring Cloud LoadBalancer (replaced Ribbon in Spring Boot 2.4+)
=> Example with OpenFeign :
@FeignClient(name = "payment-service")
public interface PaymentClient {
@GetMapping("/pay")
String pay();
}
=> Feign automatically discovers instances via Eureka
=> Spring Cloud LoadBalancer picks one instance (round-robin by default)
2. Ribbon (Legacy – Deprecated in newer versions)
=> Older Spring Cloud used Ribbon for client-side load balancing
=> Still works in older projects, but Spring Cloud LoadBalancer is now the default
3. Server-side Load Balancing (Optional)
=> Use API Gateway (Spring Cloud Gateway) or external LB (Nginx, AWS ALB, Kubernetes Ingress)
=> Gateway queries Eureka → routes traffic to instances.
NOTE : The Eureka Server can (and in production should) have multiple instances/servers running simultaneously. This is called Eureka Server HA (High Availability) or peer-aware mode.
Key Configuration (Client-Side)
eureka:
client:
service-url:
defaultZone: http://localhost:8761/eureka/
register-with-eureka: true
fetch-registry: true
# Load balancer (optional tuning)
spring:
cloud:
loadbalancer:
configurations: round-robin # or weighted, random