Registry, Config & Gateway Together
Registry, Config & Gateway Together
You have studied Eureka (service registry), Spring Cloud Config Server (centralised configuration), and Spring Cloud Gateway (edge routing) as individual pieces. In production, all three run at the same time and interact with each other in ways that are not obvious when you look at each tool in isolation. This lesson wires them together into a single coherent mental model — and into working code — so you can reason about the system as a whole, diagnose cross-cutting failures, and apply the security controls that span all three layers.
How the Three Infrastructure Services Relate
Think of the three services as concentric rings of responsibility:
- Config Server is the innermost ring. It starts first and provides runtime configuration to every other service, including Eureka and the Gateway itself.
- Eureka Server is the next ring. It starts after receiving its own config, then acts as the phone book every service — including the Gateway — consults to find instance addresses.
- API Gateway is the outermost ring. It starts last, fetches its route table from Config, discovers real instance addresses from Eureka, and then accepts external traffic.
Business microservices sit behind all three rings: they pull config from Config Server, register themselves in Eureka, and receive routed requests from the Gateway.
lb:// URIs and will return 503 for every route. Orchestrators like Kubernetes solve this with readiness probes; with Docker Compose, use depends_on with condition: service_healthy.
Config Server: Serving Configuration to Infrastructure Services Too
A common mistake is treating Config Server as a service for business microservices only. Eureka and the Gateway are themselves Spring Boot applications and should also bootstrap from Config Server. The bootstrap properties for each are minimal — just enough to find Config Server — and everything else comes over the wire.
Config Server then serves files named eureka-server.yml and api-gateway.yml (plus a shared application.yml for common properties) from its Git-backed repository. All Eureka peer URLs, all Gateway route definitions, and all TLS settings can live in that repository, versioned and auditable.
Eureka Registration Flow for Every Service
When a business microservice — say, order-service — starts, the following sequence occurs automatically if you have added the spring-cloud-starter-netflix-eureka-client dependency:
- The service fetches its full configuration from Config Server (including the Eureka URL).
- It sends a
POST /eureka/apps/ORDER-SERVICEregistration heartbeat to Eureka, including its IP, port, health-check URL, and metadata map. - Eureka stores the instance in its registry and broadcasts the change to other Eureka peers (if clustered).
- The API Gateway, which polls Eureka every 30 seconds by default, picks up the new instance and adds it to its load-balancer pool for the
lb://order-serviceroute.
Setting server.port=0 lets the OS assign a free port on every instance. Because Eureka records the actual port at registration time, you can run three instances of order-service on the same host without port collisions — each gets a unique entry in the registry.
Gateway Route Discovery via Eureka
The simplest Gateway configuration uses automatic route discovery: every application registered in Eureka automatically gets a route under /{service-id}/**. This is convenient for development but exposes internal services that should not be public. In production, define routes explicitly.
The lb:// scheme is the contract between Gateway and the Spring Cloud LoadBalancer abstraction. At request time, Gateway asks LoadBalancer to resolve order-service; LoadBalancer queries the local Eureka cache and returns one healthy instance address using round-robin (or a custom strategy). Gateway then rewrites the request URI to http://<resolved-ip>:<resolved-port>/orders/... and forwards it.
prefer-ip-address: true in Eureka clients. In containerised environments, hostnames are rarely resolvable across services, but IP addresses always are. Without this flag, Eureka registers the container hostname (e.g. a3f9c1b2), which the Gateway cannot resolve from a different container network.
Security Across All Three Layers
The registry, config, and gateway each have their own security surface. When they run together, the surfaces overlap and you need a coherent policy:
- Config Server: Protect the
/encryptand/decryptendpoints with HTTP Basic or OAuth2. Encrypt all secrets (passwords, signing keys) stored in the Git repository using{cipher}prefix. Only the Config Server holds the private key; clients receive already-decrypted values over an internal-only TLS channel. - Eureka Server: Enable HTTP Basic authentication. All clients must supply the credentials in the
defaultZoneURL:http://user:password@eureka-server:8761/eureka/. Without authentication, any process on the same network can register a fake instance and intercept traffic. - API Gateway: This is the only component that accepts external traffic. Apply JWT validation, OAuth2 resource server configuration, CORS policies, and rate limiting here — not in individual microservices. Internal service-to-service calls that arrive through a load balancer (not through the Gateway) should still carry a propagated JWT or a machine-to-machine token so that network-layer breaches do not give unrestricted internal access.
Health Checks and Readiness in a Three-Layer Setup
Spring Boot Actuator exposes /actuator/health on every service. When all three infrastructure services are present, the health endpoint of the Gateway becomes a useful composite indicator: it depends on Eureka being reachable, which in turn depends on Config Server having bootstrapped correctly. Configure each service to report its upstream dependencies:
/actuator through the public Gateway route. Actuator endpoints reveal topology, metrics, and — if /refresh or /busrefresh is included — let callers mutate running configuration. Either block actuator paths at the Gateway level with a route predicate, or deploy actuator on a separate management port (management.server.port) that is not accessible from the public internet.
End-to-End Request Trace
Putting it all together, here is what happens when a mobile client calls POST https://api.example.com/api/orders:
- Gateway receives the request. The JWT filter validates the Bearer token against the JWKS URI (configured via Config Server). If invalid, it returns 401 immediately — the request never reaches the microservice.
- Route matching. The predicate
Path=/api/orders/**matches; theStripPrefix=1filter rewrites the path to/orders. - Eureka resolution. LoadBalancer queries the local Eureka cache for
order-serviceand picks one instance (e.g.,10.0.1.42:52381). - Forwarding. Gateway forwards
POST http://10.0.1.42:52381/orders, appending a propagation header (X-Forwarded-For, and optionally a correlation ID from theAddRequestHeaderfilter). - Response.
order-servicereturns 201; Gateway relays it with any response filters applied (e.g., stripping internal headers likeX-Application-Context).
Every configuration value involved in steps 1–5 — the JWKS URI, the route table, the Eureka URL — was delivered by Config Server from a Git-backed repository, so changing any of them is a Git commit followed by a /actuator/busrefresh call, with no redeployment required.
Summary
Config Server, Eureka, and the API Gateway form a mutually-supporting trio: Config distributes configuration to the other two; Eureka maintains the live map of running instances; the Gateway uses both to accept, authenticate, and intelligently route external traffic. Hardening all three consistently — encrypted secrets, authenticated registry, JWT-validated edge — closes the security perimeter without pushing that complexity into every individual microservice. In the final lesson of this tutorial you will apply everything to a small but realistic discoverable microservices project.