Home Java Spring Cloud Bootstrapping: Config, Discovery & Setup from a Senior Dev
Advanced 5 min · July 14, 2026

Spring Cloud Bootstrapping: Config, Discovery & Setup from a Senior Dev

Learn to bootstrap Spring Cloud microservices with Config Server and Eureka.

N
Naren Founder & Principal Engineer

20+ years shipping production Java in banking & fintech. Drawn from code that ran under real load.

Follow
Production
production tested
July 15, 2026
last updated
2,398
articles · all by Naren
Before you start⏱ 25-30 min read
  • Java 17+
  • Spring Boot 3.x
  • Basic understanding of microservices architecture
  • Familiarity with Spring Boot application properties
  • Git (for Config Server repository)
 ● Production Incident 🔎 Debug Guide ⚙ Triage Commands
Quick Answer
  • Use Spring Cloud Config Server for externalized configuration; avoid embedding config in JARs.
  • Service discovery with Netflix Eureka is still solid for most teams; Consul is an alternative if you need health checking.
  • Start with Spring Initializr and add spring-cloud-starter-config, spring-cloud-starter-netflix-eureka-client.
  • Always use bootstrap.yml for bootstrap-phase config; application.yml is loaded later.
  • Never hardcode service URLs; use discovery client or load-balanced RestTemplate.
✦ Definition~90s read
What is Spring Cloud Bootstrapping?

Spring Cloud Bootstrapping is the initial setup phase where you configure external configuration, service discovery, and essential infrastructure before your microservices fully start.

Imagine you're building a city of services (microservices).
Plain-English First

Imagine you're building a city of services (microservices). Each building needs blueprints (configuration) and a phone book (service discovery). Spring Cloud Config Server is the blueprint office where all buildings get their plans. Eureka is the phone book that tells each building where the others are. Bootstrapping is the process of setting up the blueprint office and phone book before any building can function.

⚙ Browser compatibility
Latest versions — ✓ supported
ChromeFirefoxSafariEdge

After 15 years of building microservices—starting with the Netflix stack when it was still called 'Cloud Native'—I've seen every possible way to screw up a Spring Cloud bootstrap. I've debugged production outages at 2 AM because someone put a database URL in application.yml instead of bootstrap.yml. I've watched teams spend weeks trying to figure out why their services couldn't find each other, only to realize they forgot to annotate their main class with @EnableDiscoveryClient.

Here's the hard truth: most teams get the initial setup wrong. They treat bootstrap like an afterthought, copy-paste configs from tutorials, and then wonder why their system falls apart when they add a third service. This article is the bootstrapping guide I wish I had when I started. We'll cover configuration management with Spring Cloud Config Server, service discovery with Eureka, and the critical setup patterns that separate production-grade systems from hobby projects.

You'll learn why bootstrap.yml exists, how to avoid circular dependencies between config and discovery, and what the official docs conveniently omit about real-world deployments. If you're building microservices with Spring Cloud, this is your starting point—get it wrong and everything downstream suffers.

Why Bootstrap.yml Exists (And Why Most Devs Get It Wrong)

Spring Cloud's bootstrap context is loaded before the main application context. This is not a quirk—it's a necessity. The bootstrap phase is responsible for setting up the infrastructure your application needs to even start: connecting to a Config Server, initializing encryption, setting up service discovery bindings.

I've seen countless developers try to put spring.cloud.config.uri in application.yml, only to watch their services fail with 'Could not resolve placeholder'. The bootstrap context doesn't have access to application.yml—it hasn't been loaded yet. That's why bootstrap.yml exists.

Here's the load order, straight from the Spring Cloud docs (but buried in a footnote): 1. Bootstrap context loads bootstrap.yml (or bootstrap.properties) 2. Bootstrap context connects to Config Server (if configured) 3. Config Server returns application.yml (or profile-specific) 4. Main application context loads

If you need a property during step 2, it must be in bootstrap.yml. This includes: - spring.cloud.config.uri - spring.cloud.config.username/password - spring.cloud.config.fail-fast - Encryption keys (spring.cloud.config.server.encrypt.*) - Service discovery bootstrap (e.g., eureka.client.serviceUrl.defaultZone if fetched from Config)

Many teams also make the mistake of putting too much in bootstrap.yml. Keep it minimal—only properties needed to bootstrap. Everything else belongs in application.yml or Config Server files.

bootstrap.ymlJAVA
1
2
3
4
5
6
7
8
9
10
11
12
13
spring:
  application:
    name: payment-service
  cloud:
    config:
      uri: http://config-server:8888
      fail-fast: true
      retry:
        initial-interval: 1000
        max-attempts: 5
  profiles:
    active: dev
⚠ Bootstrap.yml is not optional
📊 Production Insight
In production, set spring.cloud.config.fail-fast=true and add spring.retry to avoid transient network issues. Without fail-fast, the application will silently fail to load config and might start with default values, causing data corruption.
🎯 Key Takeaway
Always put Config Server URI, fail-fast settings, and encryption keys in bootstrap.yml. This file is loaded before the main application context and is essential for bootstrapping.

Setting Up Spring Cloud Config Server

The Config Server is the backbone of your microservice configuration. It centralizes all property files and serves them to clients on startup. Here's how to set it up properly.

First, create a new Spring Boot application with the Config Server dependency. Add @EnableConfigServer to your main class. Then configure the backend where config files are stored. Git is the most common choice for production—it gives you versioning, auditing, and branching per environment.

spring: cloud: config: server: git: uri: https://github.com/myorg/config-repo search-paths: '{application}' default-label: main

I strongly recommend using a private Git repository with SSH keys or HTTPS credentials. Never store secrets (passwords, API keys) in plain text in the config repo. Use encryption with a symmetric key or integrate with a vault like HashiCorp Vault.

One production gotcha: if your Git repo is not accessible during startup, the Config Server will fail to initialize. Use a local filesystem backend for development, but always use Git for staging and production. Also, consider setting spring.cloud.config.server.git.clone-on-start=false to avoid cloning the entire repo on startup—instead, it clones lazily on first request.

For high availability, run multiple Config Server instances behind a load balancer. They all read from the same Git repo, so they are stateless. Set spring.cloud.config.server.git.force-pull=true to ensure they always fetch the latest version.

ConfigServerApplication.javaJAVA
1
2
3
4
5
6
7
8
9
10
11
12
13
14
package com.thecodeforge.configserver;

import org.springframework.boot.SpringApplication;
import org.springframework.boot.autoconfigure.SpringBootApplication;
import org.springframework.cloud.config.server.EnableConfigServer;

@SpringBootApplication
@EnableConfigServer
public class ConfigServerApplication {
    public static void main(String[] args) {
        SpringApplication.run(ConfigServerApplication.class, args);
    }
}
💡Use a dedicated config repo per environment
📊 Production Insight
If your Config Server is down, all dependent services will fail to start unless you have a local fallback. Use spring.cloud.config.allow-override=true and spring.cloud.config.override-system-properties=true to allow environment variables to override config server values in emergencies.
🎯 Key Takeaway
Config Server with Git backend is production-ready. Use encryption for secrets, run multiple instances for HA, and always use fail-fast on clients.

Service Discovery with Eureka: What the Official Docs Won't Tell You

Eureka is the most battle-tested service discovery solution in the Spring Cloud ecosystem. It's simple, reliable, and works well for most teams. But the official docs gloss over several critical details.

First, never use Eureka's self-preservation mode in development. It's designed for production to prevent cascading failures, but in dev it can cause instances to remain registered after they've stopped. Disable it with eureka.server.enableSelfPreservation=false.

Second, set appropriate renewal thresholds. The default lease renewal interval is 30 seconds, and the lease expiration duration is 90 seconds. For high-traffic services, you might want shorter intervals. But be careful—too short can cause unnecessary churn.

Third, always configure Eureka client with fetchRegistry=true and registerWithEureka=true (these are defaults). If you have a service that doesn't need to be discovered (like a gateway that knows all routes statically), you can set registerWithEureka=false.

Here's a common mistake: forgetting to add @EnableDiscoveryClient on the main class. Without it, the service won't register with Eureka. Also, ensure spring.application.name is set—Eureka uses it as the service ID.

For high availability, run multiple Eureka servers that peer with each other. Each server registers with the others, creating a cluster. Use DNS or a load balancer to point clients to the cluster.

EurekaServerApplication.javaJAVA
1
2
3
4
5
6
7
8
9
10
11
12
13
14
package com.thecodeforge.eurekaserver;

import org.springframework.boot.SpringApplication;
import org.springframework.boot.autoconfigure.SpringBootApplication;
import org.springframework.cloud.netflix.eureka.server.EnableEurekaServer;

@SpringBootApplication
@EnableEurekaServer
public class EurekaServerApplication {
    public static void main(String[] args) {
        SpringApplication.run(EurekaServerApplication.class, args);
    }
}
🔥Eureka vs Consul vs Kubernetes
📊 Production Insight
Eureka's eventual consistency model means that after a service goes down, it might take up to 90 seconds (lease expiration) for Eureka to remove it. Clients that cache the registry might still try to call the dead instance. Use a load balancer with health checks (like Ribbon or Spring Cloud LoadBalancer) to mitigate this.
🎯 Key Takeaway
Eureka is simple and effective. Disable self-preservation in dev, configure lease settings appropriately, and always add @EnableDiscoveryClient.

Bootstrap Order: Config Server vs Eureka – The Chicken-and-Egg Problem

Here's a classic bootstrap puzzle: your services need to connect to Config Server to get the Eureka URL, but they also need Eureka to find the Config Server. This circular dependency can be solved in several ways.

Option 1: Hardcode the Config Server URI in bootstrap.yml. This is the simplest and most common approach. The Config Server is a known infrastructure component, so its URL rarely changes. Use a DNS name or load balancer to make it resilient.

Option 2: Use a separate discovery-first bootstrap. Some teams configure Eureka URL directly in bootstrap.yml, then fetch all other config from Config Server via discovery. This works but adds complexity.

Option 3: Use Spring Cloud Config's native discovery support. Set spring.cloud.config.discovery.enabled=true and provide the Eureka URL in bootstrap.yml. The Config Server client will first register with Eureka, then query Eureka to find the Config Server. This is elegant but adds a startup dependency on Eureka.

I recommend Option 1 for most teams. It's straightforward and avoids the extra startup complexity. For large deployments with many microservices, Option 3 can reduce duplication but requires careful orchestration.

One more thing: if you're using Config Server to serve Eureka configuration, ensure that the Config Server itself is not dependent on Eureka. Otherwise, you have a circular dependency at the infrastructure level.

bootstrap.ymlJAVA
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
# Option 1: Hardcode Config Server URI
spring:
  cloud:
    config:
      uri: http://config-server:8888

# Option 3: Use discovery to find Config Server
# spring:
#   cloud:
#     config:
#       discovery:
#         enabled: true
#         service-id: config-server
#   eureka:
#     client:
#       serviceUrl:
#         defaultZone: http://eureka:8761/eureka/
⚠ Avoid circular dependencies at all costs
📊 Production Insight
In a production outage where both Config Server and Eureka went down, we had to manually restart Config Server first, then Eureka, then all other services. A script that enforces startup order can save you during incident response.
🎯 Key Takeaway
Hardcode Config Server URI in bootstrap.yml to avoid circular dependencies. Use discovery-based config only if you understand the startup implications.

What the Official Docs Won't Tell You About Bootstrap Configuration

The Spring Cloud documentation is comprehensive, but it hides several critical details that only come to light after you've been burned in production.

1. Bootstrap.yml is not the only bootstrap file. Spring Cloud also loads bootstrap.properties and bootstrap-{profile}.yml. You can use profile-specific bootstrap files to configure different Config Server URIs per environment. For example, bootstrap-dev.yml can point to a local Config Server, while bootstrap-prod.yml points to the production one.

2. Property precedence is tricky. During bootstrap, properties from bootstrap.yml have the highest precedence, but after the main context loads, application.yml properties can override them. If you need a bootstrap property to absolutely not be overridden, use spring.cloud.config.override-none=true.

3. Encryption context is separate. If you use Spring Cloud Config's encryption features, the encryption key must be available during bootstrap. This means either hardcoding it in bootstrap.yml (bad practice) or setting it as an environment variable or system property. The official docs don't emphasize this enough.

4. Fail-fast and retry are not enabled by default. Without fail-fast, if the Config Server is unreachable, the application will start with default values or fail later with confusing errors. Always set spring.cloud.config.fail-fast=true and configure retry settings.

5. Bootstrap context is not destroyed. Some developers assume that the bootstrap context is discarded after the main context loads. It's not—it remains as a parent context. This can cause issues if you have beans with the same names in both contexts. Use @Primary or explicit bean names to avoid conflicts.

bootstrap-dev.ymlJAVA
1
2
3
4
5
6
7
8
spring:
  cloud:
    config:
      uri: http://localhost:8888
      fail-fast: true
encrypt:
  key: dev-encryption-key
💡Use environment variables for sensitive bootstrap properties
📊 Production Insight
I once spent 4 hours debugging why a production service was using dev config. Turns out, bootstrap-dev.yml was being picked up because the SPRING_PROFILES_ACTIVE environment variable was set to 'dev' in the production container. Always explicitly set profiles in production.
🎯 Key Takeaway
Bootstrap has hidden complexities: profile-specific files, property precedence, encryption context, and fail-fast settings. Read the docs carefully and test your bootstrap configuration in a staging environment.

Integrating with Other Spring Cloud Components

Once you have Config Server and Eureka running, you can integrate other Spring Cloud components. Here's a quick overview of how they fit into the bootstrap picture.

Spring Cloud Gateway: The API gateway uses service discovery to route requests to registered services. Configure it with spring.cloud.gateway.discovery.locator.enabled=true to automatically create routes based on Eureka service IDs. No need to hardcode URLs.

Feign Clients: Feign (or OpenFeign) integrates with Eureka and Ribbon (or Spring Cloud LoadBalancer) to make inter-service calls. Annotate your Feign client interface with @FeignClient(name = "payment-service") and it will use discovery to find instances.

Resilience4j Circuit Breaker: Integrate with Feign or RestTemplate to add circuit breakers. Configure fallback methods and thresholds via Config Server properties.

Spring Cloud Bus: Used to propagate config changes across services. It requires a message broker (RabbitMQ or Kafka). The bus configuration is typically in application.yml, not bootstrap, because it's not needed for startup.

Spring Cloud Sleuth: Distributed tracing. Add spring-cloud-starter-sleuth and it will automatically add trace IDs to logs. No bootstrap changes needed.

All these components rely on the bootstrap foundation you've set up. A solid bootstrap ensures that your services can find each other, load the right configuration, and handle failures gracefully.

bootstrap.yml (complete example)JAVA
1
2
3
4
5
6
7
8
9
10
11
12
13
14
spring:
  application:
    name: order-service
  cloud:
    config:
      uri: http://config-server:8888
      fail-fast: true
      retry:
        initial-interval: 1000
        max-attempts: 5
        multiplier: 1.5
  profiles:
    active: ${SPRING_PROFILES_ACTIVE:dev}
🔥Spring Cloud LoadBalancer replaces Ribbon
📊 Production Insight
In a recent project, we had a gateway that couldn't route to services because the discovery locator was not enabled. The gateway was using hardcoded URLs, which worked in dev but broke in production when instances scaled. Always use discovery-based routing.
🎯 Key Takeaway
A proper bootstrap enables seamless integration with Gateway, Feign, Resilience4j, and other Spring Cloud components. Invest time in getting the foundation right.
● Production incidentPOST-MORTEMseverity: high

The Bootstrap YAML That Took Down Production

Symptom
After deploying a new version of the payment service, all instances failed to start with: 'java.lang.IllegalStateException: Could not resolve placeholder 'config.server.url' in value "${config.server.url}"'. The config server itself was running fine.
Assumption
The developer assumed that application.properties would be loaded before the Config Server client tried to connect. They had set spring.cloud.config.uri in application.properties, thinking it would be available during bootstrap.
Root cause
The Config Server client runs during the bootstrap phase, before application.properties is loaded. The URI must be defined in bootstrap.yml (or bootstrap.properties) because that file is loaded first. The team had moved all config to application.properties during a refactor, breaking the bootstrap sequence.
Fix
Moved spring.cloud.config.uri back to bootstrap.yml, and ensured all bootstrap-phase properties (like encryption key, discovery settings) were in bootstrap.yml or bootstrap.properties. Added a CI check that fails the build if bootstrap.yml is missing required properties.
Key lesson
  • Always define Config Server URI in bootstrap.yml, not application.yml.
  • Treat bootstrap.yml as sacred—it's loaded before anything else.
  • Add a startup check that validates bootstrap configuration.
  • Use Spring Cloud Config's fail-fast and retry settings to avoid silent failures.
  • Never refactor bootstrap properties into application files without understanding the load order.
Production debug guideSymptom to Action4 entries
Symptom · 01
Service fails to start with 'Could not resolve placeholder' for config values.
Fix
Check if the placeholder is defined in bootstrap.yml or application.yml. If it's a Config Server property, it must be in bootstrap.yml. Enable debug logging: --debug or logging.level.org.springframework.cloud=DEBUG.
Symptom · 02
Service cannot register with Eureka; 'Connection refused' on Eureka port.
Fix
Verify Eureka server is running and reachable. Check spring.cloud.config.uri in bootstrap.yml if using Config Server to fetch Eureka URL. Ensure eureka.client.serviceUrl.defaultZone is correct.
Symptom · 03
Config Server returns 404 for service config.
Fix
Verify the config file naming convention: {application}-{profile}.yml (e.g., payment-service-dev.yml). Check that spring.application.name matches the config file base name.
Symptom · 04
Service starts but uses wrong configuration (e.g., connects to prod DB in dev).
Fix
Check which profile is active. Log 'Active Profiles: ' + Arrays.toString(env.getActiveProfiles()) at startup. Ensure spring.profiles.active is set correctly (e.g., via environment variable or bootstrap.yml).
★ Quick Debug Cheat SheetFast commands and fixes for common Spring Cloud bootstrapping issues
Config placeholder not resolved
Immediate action
Check bootstrap.yml for spring.cloud.config.uri
Commands
curl -v http://config-server:8888/myapp/default
java -jar myapp.jar --debug
Fix now
Add spring.cloud.config.uri to bootstrap.yml and restart
Service not registered in Eureka+
Immediate action
Check Eureka dashboard (http://eureka:8761)
Commands
curl http://eureka:8761/eureka/apps
docker logs <eureka-container>
Fix now
Add @EnableDiscoveryClient and ensure eureka.client.serviceUrl.defaultZone is correct
Wrong profile active+
Immediate action
Check startup logs for 'Active Profiles'
Commands
java -jar myapp.jar --spring.profiles.active=dev
env | grep SPRING_PROFILES_ACTIVE
Fix now
Set SPRING_PROFILES_ACTIVE environment variable or add to bootstrap.yml
ComponentPurposeBootstrap RequiredDependency
Config ServerCentralized configurationYes (URI in bootstrap.yml)Git backend
EurekaService discoveryYes (URL in bootstrap.yml or Config)Config Server (optional)
GatewayAPI routingNo (uses discovery)Eureka/Consul
Feign ClientDeclarative HTTP clientsNoEureka/Consul + LoadBalancer
Resilience4jCircuit breakerNo (config from Config Server)Config Server (optional)
Spring Cloud BusConfig propagationNo (needs message broker)RabbitMQ/Kafka
⚙ Quick Reference
5 commands from this guide
FileCommand / CodePurpose
bootstrap.ymlspring:Why Bootstrap.yml Exists (And Why Most Devs Get It Wrong)
ConfigServerApplication.java@SpringBootApplicationSetting Up Spring Cloud Config Server
EurekaServerApplication.java@SpringBootApplicationService Discovery with Eureka
bootstrap-dev.ymlspring:What the Official Docs Won't Tell You About Bootstrap Config
bootstrap.yml (complete example)spring:Integrating with Other Spring Cloud Components

Key takeaways

1
Always define Config Server URI and fail-fast settings in bootstrap.yml, not application.yml.
2
Use Eureka for service discovery with @EnableDiscoveryClient and configure lease settings appropriately.
3
Avoid circular dependencies between Config Server and Eureka by hardcoding one of their URLs.
4
Leverage profile-specific bootstrap files for environment-specific configuration.
5
Integrate with other Spring Cloud components (Gateway, Feign, Resilience4j) using discovery-based patterns.
INTERVIEW PREP · PRACTICE MODE

Interview Questions on This Topic

Q01SENIOR
Explain the bootstrap phase in Spring Cloud. What is its purpose and how...
Q02SENIOR
How would you handle a circular dependency where Config Server needs Eur...
Q03JUNIOR
What is the default lease renewal interval in Eureka and why would you c...
Q01 of 03SENIOR

Explain the bootstrap phase in Spring Cloud. What is its purpose and how does it differ from the main application context?

ANSWER
The bootstrap phase is the initial context loading that occurs before the main application context. Its purpose is to set up infrastructure needed for the application to start, such as connecting to a Config Server, initializing encryption, and setting up service discovery bindings. The bootstrap context reads bootstrap.yml (or bootstrap.properties) and is a parent of the main context. Properties loaded in bootstrap can be overridden by the main context, but bootstrap properties have higher precedence during the bootstrap phase.
FAQ · 5 QUESTIONS

Frequently Asked Questions

01
Do I need both Config Server and Eureka?
02
What if my Config Server is down? Can my services still start?
03
Why can't I put spring.cloud.config.uri in application.yml?
04
How do I handle secrets in configuration?
05
Can I use Consul instead of Eureka for service discovery?
N
Naren Founder & Principal Engineer

20+ years shipping production Java in banking & fintech. Drawn from code that ran under real load.

Follow
Verified
production tested
July 15, 2026
last updated
2,398
articles · all by Naren
🔥

That's Spring Cloud. Mark it forged?

5 min read · try the examples if you haven't

Previous
Spring Cloud AWS EC2: Instance Management and Elastic Compute Integration
32 / 34 · Spring Cloud
Next
Spring Cloud Securing Services: OAuth2, JWT, and Service-to-Service Authentication