Microservices Intro + Spring Cloud Config/Eureka

  1. What is a microservice architecture? Benefits vs monolith?
  2. Main challenges of microservices (distributed systems, data consistency, communication, deployment)?
  3. What is Spring Cloud? Why use it with Spring Boot?
  4. Spring Cloud Config Server – purpose (centralized config management)?
  5. How Config Server works with Git backend?
  6. Config Client – how to fetch config from Config Server?
  7. Spring Cloud Eureka – service registry & discovery?
  8. Eureka Server setup steps?
  9. Eureka Client registration (@EnableDiscoveryClient)?
  10. Difference between Config Server vs application.properties?
  11. Refresh config at runtime with @RefreshScope?
  12. Best practices for microservices config management?
  13. Eureka self-preservation mode – what is it and when it activates?
  14. When to use Config Server vs external tools (Consul, Vault)?
  15. 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

AspectMonolithic ArchitectureMicroservice ArchitectureWinner (in most cases)
StructureSingle codebase, single deployable unitMany small, independent servicesMicroservices (flexibility)
Development speedFast initially, slows down as app growsSlower initially, faster at scaleMicroservices (long-term)
ScalabilityScale entire app (vertical or horizontal)Scale individual services independentlyMicroservices
Technology choiceOne tech stack for whole appDifferent tech per service (Java, Python, Node.js, etc.)Microservices
Fault isolationOne failure can crash entire appFailure in one service usually isolatedMicroservices
DeploymentFull redeploy for any changeIndependent deploy of single serviceMicroservices
Team structureLarge team on one codebaseSmall, autonomous teams per serviceMicroservices
ComplexitySimple at small scaleHigh complexity (network, distributed tracing, etc.)Monolith (early stage)
DatabaseSingle shared DBDatabase per service (polyglot persistence)Microservices
TestingEasier unit tests, harder end-to-endHarder integration, easier individual service testsDepends on scale
Performance overheadLow (in-process calls)Higher (network calls, serialization)Monolith
MaintenanceBecomes nightmare as code growsEasier to maintain individual servicesMicroservices (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

FeaturegRPCTraditional REST (JSON/HTTP)
ProtocolHTTP/2 (binary)HTTP/1.1 or HTTP/2 (text-based)
Data FormatProtocol Buffers (binary, compact)JSON (text, larger)
PerformanceVery high (faster, lower latency)Slower (more overhead)
Contract.proto file (strongly typed)OpenAPI/Swagger (optional)
StreamingYes (unary, server, client, bidirectional)Limited (only server-sent events)
Language Support10+ languages (Java, Go, Python, C++, etc.)Mostly language-agnostic via HTTP
Typical Use CaseInternal microservices communicationPublic APIs, browser/mobile clients
=> In Spring Boot, REST via OpenFeign is more common, but gRPC is used for performance-critical paths

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)

  1. Spring Cloud Config
  2. Spring Cloud Netflix Eureka
  3. Spring Cloud Gateway
  4. Spring Cloud OpenFeign
  5. Spring Cloud LoadBalancer
  6. Spring Cloud Circuit Breaker / Resilence4j
  7. Spring Cloud Sleuth + Zipkin
ComponentPurposePopular Tools / Alternatives
Spring Cloud ConfigCentralized configuration management (external config for all services)Git, Vault, Consul
Spring Cloud Netflix EurekaService registry & discovery (services register themselves, clients find them)Consul, Kubernetes DNS
Spring Cloud GatewayAPI Gateway (routing, load balancing, security, rate limiting)Kong, Zuul (older)
Spring Cloud OpenFeignDeclarative HTTP client (simpler than RestTemplate)WebClient, RestTemplate
Spring Cloud LoadBalancerClient-side load balancingRibbon (older)
Resilience4j / Spring Cloud Circuit BreakerFault tolerance (circuit breaker, retry, rate limiter, bulkhead)Hystrix (deprecated)
Spring Cloud Sleuth + ZipkinDistributed tracing (track requests across services)OpenTelemetry, Jaeger

Why Use Spring Cloud with Spring Boot?

ScenarioSpring Boot AloneSpring Boot + Spring Cloud
Configurationapplication.properties per serviceCentralized config via Config Server + Git
Service discoveryHardcoded URLs or manual configEureka/Consul — services auto-register & discover
Load balancingManual or external LBClient-side LB (Spring Cloud LoadBalancer)
Fault toleranceManual try-catch/retriesResilience4j circuit breaker + retry automatically
API GatewayNo built-inSpring Cloud Gateway for routing/security
Tracing across servicesHard (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)

Aspectapplication.properties / application.ymlSpring Cloud Config ServerWinner (in which scenario)
Location of configInside 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 fileYes — single source of truth for all servicesConfig Server
Change config without redeployNo — requires rebuild & redeploy of the appYes — change in Git → refresh via /actuator/refreshConfig Server
Environment-specific configSeparate files (application-dev.properties, etc.)Same file with profile suffix (employee-service-dev.yml)Both good, Config Server more scalable
Version controlDifficult (config in code repo, but often ignored)Full Git history, audit trail, rollback easyConfig Server
Security / Sensitive dataHard to secure (in JAR or repo)Can encrypt values, integrate Vault, external secretsConfig Server
Refresh at runtimeNo (restart needed)Yes — with @RefreshScope + /actuator/refreshConfig Server
Use caseSimple apps, monoliths, local developmentMicroservices, cloud-native, multiple environmentsConfig Server for scale
Setup complexityZero (built-in)Medium (separate server, Git setup, client config)application.properties
ScalabilityPoor for 10–100 services (update all manually)Excellent (change once → all services get it)Config Server
FallbackLocal file always availableFallback to local config if Config Server down (fail-fast option)Both
Refresh config at runtime with @RefreshScope?

=> @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