The goal of this lecture is to understand what mistakes can happen when managing configurations in microservices, and how to avoid them. After all, avoiding mistakes is like not catching a NullPointerException in Java: everyone knows it's possible, but in practice it's not that simple.
Common mistakes in configuration and secret management
1. Storing configurations in code
One of the most common mistakes (and, honestly, one of the most "embarassing" in interviews) is storing configurations directly in code. Here's an example:
public class DatabaseConfig {
public static final String DB_URL = "jdbc:mysql://localhost:3306/mydb";
public static final String DB_USERNAME = "admin";
public static final String DB_PASSWORD = "super_secret_password";
}
Someone might say: "What's the big deal? It's convenient!". But imagine you have ten people on your team. If the password changes, everyone has to change the code and rebuild the app. And if this ends up in the repo, anyone with access to the code will get access to your "secret" super_secret_password. Welcome — data leak!
How to fix this?
- Use external configuration files (
application.properties,application.yml) or centralized configuration management systems like Spring Cloud Config. - For secrets — use specialized tools such as HashiCorp Vault.
2. Using the same configurations for all environments
Another common mistake is not having profiles for different environments — development, testing, production. Keeping a one-size-fits-all config will lead to situations like running a test database in production or accidentally sending sales reports to a test email.
How to solve?
Spring Boot profiles are your best friend! With profiles, dev, test, and prod can get different configurations.
Example of configuring DB profiles in application.yml:
spring:
profiles:
active: dev # Default active profile
---
spring:
profiles: dev
datasource:
url: jdbc:mysql://localhost:3306/dev_db
username: dev_user
password: dev_password
---
spring:
profiles: prod
datasource:
url: jdbc:mysql://prod-host:3306/prod_db
username: prod_user
password: prod_secret_password
If you switch profiles at the command line, just use the flag:
java -Dspring.profiles.active=prod -jar your-app.jar
3. Forgotten 'live' configuration updates
Problem: when you change configurations on the fly your application might keep using old values. For example, you updated connection parameters to a service, but the app keeps using the old ones until it's restarted.
How to fix?
Use Spring Cloud Bus and change notifications. Spring Cloud Bus works with message brokers (e.g., RabbitMQ, Kafka) and lets microservices learn about configuration updates without restarting.
Example of updating configurations "on the fly" in a controller:
@RestController
public class ConfigController {
@Value("${config.example.value}")
private String configValue;
@GetMapping("/config")
public String getConfigValue() {
return configValue;
}
@RefreshScope // Refreshes the value after /actuator/refresh is called
public void refreshConfig() {
// The code will automatically pick up updated values
}
}
4. Unmanaged secret storage
Some developers, even when using tools like HashiCorp Vault, don't think about proper access setup. The issue is that if access to confidential data is poorly controlled, using such tools becomes pointless.
Example of bad practice:
- All services have access to all secrets.
- No secret rotation policy.
How to fix?
- Principle of least privilege: each service should have access only to the data it needs.
- Secret rotation: set expiry timers for access keys and rotate them regularly.
Policy configuration in HashiCorp Vault (HCL example):
path "secret/data/myapp/*" {
capabilities = ["create", "read", "update", "delete", "list"]
}
path "secret/data/otherapp/*" {
capabilities = ["deny"]
}
In this example access to secrets is split by application, and one app doesn't have access to another app's secrets.
5. Versioning problems
A common error is mismatched configuration versions between microservices. For example, one microservice updated a library and uses new configuration parameters, while another remained on the old version.
How to solve?
- Version control via Git (for example, storing configurations in a repository).
- Tag configuration versions and update dependencies in sync.
6. Problems securing access to configurations
Without setting up access control, you might "share" configurations with anyone on your network.
How to fix?
- Set up authentication and authorization, for example for Spring Cloud Config Server:
spring.security.user.name=admin spring.security.user.password=secret
If you use Git as a configuration store, be sure to secure the repository with SSH keys or similar mechanisms.
7. Poor organization of configuration files
Sometimes configs are dumped together with no structure or clear usage logic. A developer spends more time searching than writing code.
How to solve? Organize configs by service and use explicit names. Example application.yml file:
my-service:
config:
timeout: 1000
retries: 3
Best practices to prevent mistakes
- Separate configs and secrets. Store confidential data (passwords, API keys) separately from regular settings. Use tools like Vault or AWS Secrets Manager.
- Use CI/CD. Automate config testing with pipelines. For example, before deployment, verify that all configurations work.
- Document configurations. Always write what a given parameter means in configuration files. Use comments and documentation in repositories.
- Consistent naming style. All configuration properties should follow a unified naming style. For example, instead of
timeoutandTIMEOUTit's better to stick tocamelCaseorsnake_case.
And remember: proper configuration management is like Robert Martin's Clean Code. It's not just pretty, it's practical. And none of your colleagues will remember you in their nightmares! Good luck!
GO TO FULL VERSION