Spring Boot Multi-Environment Configuration
Why Multi-Environment Configuration
In real projects, applications are deployed to different environments:
- Development (dev): Local development and debugging
- Testing (test): QA testing and validation
- Staging: Pre-production validation
- Production (prod): Live services
Different environments require different configurations: database connections, log levels, service endpoints, etc.
Approach 1: Profile-specific Configuration Files
1. File Naming Convention
shellapplication.yml # Default (shared across all environments) application-dev.yml # Development environment application-test.yml # Testing environment application-staging.yml # Staging environment application-prod.yml # Production environment
2. Configuration Examples
application.yml (Default)
yamlspring: application: name: my-service profiles: active: dev # Default to dev environment server: port: 8080 logging: level: root: INFO
application-dev.yml (Development)
yamlserver: port: 8081 spring: datasource: url: jdbc:mysql://localhost:3306/dev_db username: dev_user password: dev_pass jpa: hibernate: ddl-auto: update show-sql: true logging: level: com.example: DEBUG
application-prod.yml (Production)
yamlserver: port: 80 spring: datasource: url: jdbc:mysql://prod-db.example.com:3306/prod_db username: ${DB_USERNAME} password: ${DB_PASSWORD} hikari: maximum-pool-size: 50 jpa: hibernate: ddl-auto: validate show-sql: false logging: level: root: WARN
Approach 2: Single File with Multiple Documents
Spring Boot 2.4+ supports multiple profiles in one YAML file:
yamlspring: application: name: my-service --- spring: config: activate: on-profile: dev server: port: 8081 --- spring: config: activate: on-profile: prod server: port: 80
Activating Profiles
Method 1: Configuration File
yamlspring: profiles: active: dev
Method 2: Command Line
bashjava -jar myapp.jar --spring.profiles.active=prod
Method 3: Environment Variable
bashexport SPRING_PROFILES_ACTIVE=prod java -jar myapp.jar
Method 4: JVM System Property
bashjava -Dspring.profiles.active=prod -jar myapp.jar
Profile Groups (Spring Boot 2.4+)
Group multiple profiles together:
yamlspring: profiles: group: local: - dev - local-db - local-cache production: - prod - prod-db - prod-cache
Usage:
bashjava -jar myapp.jar --spring.profiles.active=local # Activates: dev, local-db, local-cache
Conditional Bean Configuration
Use @Profile annotation for environment-specific beans:
java@Configuration public class DataSourceConfig { @Bean @Profile("dev") public DataSource devDataSource() { // Dev datasource configuration } @Bean @Profile("prod") public DataSource prodDataSource() { // Production datasource configuration } @Bean @Profile("!prod") // Non-production environments public MockService mockService() { return new MockService(); } }
Accessing Active Profiles in Code
java@Component public class EnvironmentChecker implements CommandLineRunner { @Autowired private Environment environment; @Override public void run(String... args) { String[] activeProfiles = environment.getActiveProfiles(); System.out.println("Active profiles: " + String.join(", ", activeProfiles)); if (environment.acceptsProfiles(Profiles.of("dev"))) { System.out.println("Development mode"); } } }
Configuration Loading Priority
Priority order (high to low):
- Command line arguments
- JNDI properties
- Java System properties
- OS environment variables
RandomValuePropertySource- External
application-{profile}.properties - Internal
application-{profile}.properties - External
application.properties - Internal
application.properties - @PropertySource annotations
- SpringApplication default properties
Key Rules:
application-{profile}.ymloverridesapplication.yml- Higher priority overrides lower priority for same keys
Sensitive Information Encryption
Option 1: Environment Variables
yamlspring: datasource: password: ${DB_PASSWORD}
Option 2: Jasypt Encryption
yamlspring: datasource: password: ENC(encrypted_password) jasypt: encryptor: password: ${JASYPT_ENCRYPTOR_PASSWORD}
Best Practices
1. Configuration Layering
yaml# application.yml - Only truly shared configs spring: application: name: my-service
2. Use Configuration Properties Classes
java@ConfigurationProperties(prefix = "app") @Component public class AppProperties { private String name; private String version; // getters and setters }
3. Production Checklist
- Disable debug mode:
debug: false - Disable SQL logging:
show-sql: false - Set appropriate log levels
- Configure connection pool
- Use environment variables for secrets
- Configure health check endpoints
- Set appropriate timeout values
Summary
| Feature | Description |
|---|---|
| File Separation | application-{profile}.yml |
| Multi-document | Use --- separator |
| Activation | Config, CLI, env var, JVM arg |
| Conditional Beans | @Profile annotation |
| Profile Groups | spring.profiles.group |
| Priority | CLI > Env Var > Config File |