Documentation Index
Fetch the complete documentation index at: https://resources.devweekends.com/llms.txt
Use this file to discover all available pages before exploring further.
Distributed Configuration
In a monolith,application.properties is fine. In microservices, changing a DB password in 50 services means 50 redeployments. We need Externalized Configuration.
1. Spring Cloud Config Server
This server connects to a Git repository (or filesystem) where your config files live, and serves them to microservices via an HTTP API. Setup Server:- Dependency:
spring-cloud-config-server. - Annotation:
@EnableConfigServer. application.yml:
user-service.ymlorder-service.ymlapplication.yml(Global config shared by all)
2. Config Client
The microservice that consumes the config.- Dependency:
spring-cloud-starter-config. - Bootstrap phase: The app needs to know where the Config Server is before it starts up fully.
src/main/resources/application.yml (Or bootstrap.yml in older versions):
user-service starts, it fetches configuration from the Config Server.
3. Profiles
You can haveuser-service-dev.yml and user-service-prod.yml in your git repo.
Run your app with:
java -jar app.jar --spring.profiles.active=prod
It will fetch the prod config automatically.
4. Dynamic Refresh (Hot Reload)
What if you change a property in Git and want to apply it without restarting the service?- Add
spring-boot-starter-actuatordependency. - Add
@RefreshScopeon the bean holding the config.
- Enable the refresh endpoint in
application.yml:
- Trigger the refresh:
POST http://localhost:8080/actuator/refresh
@RefreshScope.
Interview Deep-Dive
What problem does Spring Cloud Config Server solve that Kubernetes ConfigMaps and Secrets cannot? When would you use each?
What problem does Spring Cloud Config Server solve that Kubernetes ConfigMaps and Secrets cannot? When would you use each?
Strong Answer:
- Spring Cloud Config Server provides versioned, auditable, environment-specific configuration stored in Git. You get full Git history: who changed what, when, and why. You can branch configs for different environments, do pull requests for config changes, and rollback to any previous version with
git revert. It serves config via HTTP API, so any language (not just Java) can consume it. - Kubernetes ConfigMaps and Secrets are cluster-scoped. They are not versioned beyond etcd’s internal compaction. No PR workflow, no audit trail (unless you use GitOps tools like ArgoCD that sync ConfigMaps from Git). They are tightly coupled to Kubernetes — if you run services on VMs or different clouds, they do not work.
- Use Config Server when: you need Git-based versioning and audit trails (regulated industries), you have polyglot services or non-Kubernetes deployments, or you need dynamic refresh without restarting pods (Spring’s
@RefreshScopere-creates beans on/actuator/refreshwithout pod restart). - Use ConfigMaps/Secrets when: you are fully committed to Kubernetes, your config changes are rare and managed via GitOps (ArgoCD watches a Git repo and syncs ConfigMaps automatically), and you want to avoid running an additional server (Config Server is another thing to deploy, monitor, and keep available).
- The hybrid approach: use Kubernetes ConfigMaps for infrastructure config (database URLs, broker endpoints) and Spring Cloud Config for application-level feature flags and business rules that change more frequently and need audit trails.
@RefreshScope is a custom scope implemented by Spring Cloud. Beans in this scope are stored in a cache inside the RefreshScope bean. When /actuator/refresh is called, Spring Cloud fetches updated config from the Config Server, publishes a RefreshScopeRefreshedEvent, and clears the cache. The next time a refresh-scoped bean is accessed, Spring re-creates it with the new config values. In-flight requests that already hold a reference to the old bean instance continue using it — they are not interrupted. But the next request gets the new instance. There is a brief race window where some threads use the old bean and others use the new one. For most config changes (feature flags, log levels), this is fine. For critical changes (database connection strings), a rolling restart is safer because you want a clean cut.Your team has 50 microservices, and a developer accidentally pushes a bad configuration to the Config Server Git repo. How do you prevent this from taking down production?
Your team has 50 microservices, and a developer accidentally pushes a bad configuration to the Config Server Git repo. How do you prevent this from taking down production?
Strong Answer:
- Layer 1 — PR review: Config changes go through pull requests like code. Require at least one reviewer. Use branch protection rules on the config repo.
- Layer 2 — Validation: Add a CI pipeline on the config repo that validates YAML syntax, checks for required properties (database URL, port ranges), and runs a schema validator against a JSON Schema or custom validation rules. Catch typos and missing properties before merge.
- Layer 3 — Staged rollout: Do not refresh all 50 services at once. Use Spring Cloud Bus (backed by Kafka or RabbitMQ) to broadcast a refresh event, but target specific services or instances. Refresh the canary instance first, verify health, then roll out to the rest.
- Layer 4 — Fail-safe defaults: Services should start with sensible defaults even if the Config Server is unreachable. Use
spring.config.import: optional:configserver:http://...(theoptional:prefix). If the server is down, the app starts with its localapplication.ymldefaults. This prevents a Config Server outage from blocking all service startups. - Layer 5 — Rollback: Because config is in Git, rollback is
git reverton the bad commit and another refresh broadcast. The entire operation takes 30 seconds. - The scenario I have seen in production: a developer changed a connection pool size from 10 to 1000 across all services, thinking “more is better.” The database had a 200-connection max. When all 50 services refreshed, they each tried to open 1000 connections. The database rejected them all, every service’s health check failed, and the orchestrator started killing and restarting pods in a cascade. The fix: validation in the CI pipeline that enforces pool size upper bounds.
password: {cipher}AQA... are encrypted in Git and decrypted by the Config Server at serve time. The encryption key lives in the Config Server’s environment, not in Git. (2) Use HashiCorp Vault as a backend instead of Git. Spring Cloud Config supports Vault natively — the server fetches secrets from Vault on demand. (3) Use Kubernetes Secrets for sensitive values and Config Server only for non-sensitive config. (4) In AWS, use Parameter Store or Secrets Manager with the Spring Cloud AWS starter, bypassing Config Server entirely for secrets. My recommendation: never store plain-text secrets in Git, even in a private repo. Use Vault or cloud-native secret managers for secrets, and Config Server for everything else.Explain how Spring profiles work in the context of distributed configuration. How do you manage dev, staging, and production configs without duplication?
Explain how Spring profiles work in the context of distributed configuration. How do you manage dev, staging, and production configs without duplication?
Strong Answer:
- Spring profiles activate environment-specific configuration. When you run with
--spring.profiles.active=prod, Spring loadsapplication.yml(base), then overlaysapplication-prod.yml(profile-specific). Profile-specific properties override base properties. - In Config Server, the same pattern applies per service:
user-service.yml(base for all environments),user-service-dev.yml(dev overrides),user-service-prod.yml(prod overrides). The Config Server resolves:/{application}/{profile}/{label}— e.g.,/user-service/prod/mainfetches the prod config from the main branch. - To avoid duplication: put all shared properties in
application.yml(global, applies to every service) and service-specific defaults in{service-name}.yml. Profile files should contain ONLY the properties that differ between environments (database URLs, feature flags, log levels). If you find yourself copying the same property across all profile files, it belongs in the base config. - Advanced pattern: use a
commonprofile activated in all environments that contains shared infrastructure config (logging format, actuator settings). Then layer environment profiles on top. This creates a clean hierarchy:application.yml(global) ->application-common.yml(shared infra) ->user-service.yml(service defaults) ->user-service-prod.yml(prod overrides).
application-dev.yml that they forget to add to the Config Server repo. Production crashes on startup because the property is missing. Fix: (1) Run integration tests against Config Server in CI. The test starts the service with spring.profiles.active=prod and spring.config.import=configserver:http://... pointed at a test Config Server loaded from the same Git repo. If a property is missing, the test fails. (2) Use @ConfigurationProperties with @Validated — required properties are enforced at startup with fail-fast. (3) In local development, developers should configure their IDE to point at the Config Server instead of relying on local files. This is the 12-Factor App principle: keep dev and prod as similar as possible.