Discovery, Gateway and Config Questions

What is service discovery? Client-side vs server-side discovery?

Instances start and stop with dynamic IPs, so services register themselves in a registry (Eureka) and callers look up healthy instances by name.

Client-sideServer-side
Who picks the instancethe caller (Spring Cloud LoadBalancer + Eureka)a load balancer / platform (Kubernetes Service, AWS ALB)
Examplehttp://product-service/api/products with @LoadBalancedhttp://product-service.default.svc in K8s

Tip: On Kubernetes you usually do not need Eureka: the K8s Service and DNS do discovery and load balancing.

How does Eureka work? What is self-preservation mode?

  • Clients register on startup and send a heartbeat every 30 s; an instance is evicted after ~90 s without heartbeats.
  • Clients cache the registry locally and refresh it every 30 s, so calls still work if Eureka is briefly down.
  • Self-preservation: if many heartbeats are lost at once (renewals drop below 85% of expected), Eureka assumes a network problem, not dead instances, and stops evicting. Keep it on in production; disable only in local dev.
# eureka server
eureka:
  client: { register-with-eureka: false, fetch-registry: false }
---
# each service
spring.application.name: order-service
eureka.client.service-url.defaultZone: http://eureka:8761/eureka/

What does an API gateway do? Why Spring Cloud Gateway?

  • Single entry point: routing, load balancing (lb://), SSL termination.
  • Cross-cutting concerns: authentication (JWT validation), rate limiting, CORS, headers, logging, correlation ids.
  • Spring Cloud Gateway is built on Spring WebFlux + Netty (non-blocking), so a few threads handle many connections. A servlet-based variant (Gateway Server MVC) also exists.
spring:
  cloud:
    gateway:
      routes:
        - id: products
          uri: lb://product-service
          predicates:
            - Path=/api/products/**
          filters:
            - name: RequestRateLimiter
              args:
                redis-rate-limiter.replenishRate: 10
                redis-rate-limiter.burstCapacity: 20
                key-resolver: "#{@userKeyResolver}"
            - name: CircuitBreaker
              args: { name: productsCb, fallbackUri: "forward:/fallback/products" }

Note: From Spring Cloud 2025.0 the property prefix becomes spring.cloud.gateway.server.webflux.*; the old prefix still works with a deprecation warning.

How do you write a custom gateway filter, e.g. to add a correlation id?

@Component
public class CorrelationIdFilter implements GlobalFilter, Ordered {
    public Mono<Void> filter(ServerWebExchange exchange, GatewayFilterChain chain) {
        String id = Optional.ofNullable(exchange.getRequest().getHeaders().getFirst("X-Correlation-Id"))
                            .orElse(UUID.randomUUID().toString());
        ServerHttpRequest req = exchange.getRequest().mutate().header("X-Correlation-Id", id).build();
        exchange.getResponse().getHeaders().add("X-Correlation-Id", id);
        return chain.filter(exchange.mutate().request(req).build());
    }
    public int getOrder() { return -1; } // run early
}

GlobalFilter applies to every route; AbstractGatewayFilterFactory creates a named filter you attach per route in YAML. With Micrometer Tracing, the W3C traceparent header already carries a trace id end to end.

How does Spring Cloud Config work and how do you refresh config without restarting?

The Config Server serves properties from a Git repo (or Vault, JDBC) at /{application}/{profile}/{label}. Clients import it at startup.

# client application.yml
spring:
  application.name: order-service
  config.import: "optional:configserver:http://config-server:8888"
  • Beans with @RefreshScope and @ConfigurationProperties beans rebind when you POST /actuator/refresh.
  • For many instances use Spring Cloud Bus (Kafka/RabbitMQ): one POST /actuator/busrefresh refreshes all, often triggered by a Git webhook.
  • Secrets: encrypt with {cipher}... values or use Vault; never commit plain passwords.

What happens if the Config Server or Eureka is down?

  • Config Server: with optional: the service starts with local config; without it, startup fails (fail-fast, useful in prod together with spring.cloud.config.retry). Running services keep their loaded config. Run 2+ instances behind a load balancer.
  • Eureka: clients use their cached registry, so existing calls keep working; new instances cannot register. Run Eureka as a peer-aware cluster (2–3 nodes).