How to resolve Spring Boot profile configuration override when using @Profile
Problem
When I run my Spring Boot application with multiple profiles, my product service configuration overrides the default configuration unexpectedly:
$ java -jar myapp.jar --spring.profiles.active=dev,prod2026-02-22 11:45:15.234 INFO --- [ main] c.m.m.p.ProductService : Product service initialized with prod configuration2026-02-22 11:45:15.235 INFO --- [ main] c.m.m.p.ProductService : Database URL: jdbc:postgresql://prod-db:5432/mydbBut I expected to see the dev configuration since it comes first in the profile list.
Environment
- Spring Boot 3.2.1
- Java 21
- application.yml with profile-specific configurations
- Multiple active profiles: dev,prod
What happened?
I was building a multi-environment Spring Boot application with different configurations for development and production. Here’s my setup:
// Default configuration@Configurationpublic class DefaultConfig { @Bean public ProductService productService() { return new ProductService("default-db"); }}
// Development configuration@Configuration@Profile("dev")public class DevelopmentConfig { @Bean public ProductService productService() { return new ProductService("dev-db"); }}
// Production configuration@Configuration@Profile("prod")public class ProductionConfig { @Bean public ProductService productService() { return new ProductService("prod-db"); }}I can explain the key parts:
- DefaultConfig provides fallback configuration
- DevelopmentConfig activates when dev profile is active
- ProductionConfig activates when prod profile is active
But when I run with both profiles active, I get the prod configuration:
$ java -jar myapp.jar --spring.profiles.active=dev,prod2026-02-22 11:45:15.234 INFO --- [ main] c.m.m.p.ProductService : Product service initialized with prod configurationThe service is using the prod database URL instead of the dev one.
How to solve it?
I tried changing the profile order:
$ java -jar myapp.jar --spring.profiles.active=prod,devBut I still get the same result - prod configuration wins.
Then I checked the properties files:
spring: datasource: url: jdbc:postgresql://dev-db:5432/mydb
# application-prod.ymlspring: datasource: url: jdbc:postgresql://prod-db:5432/mydbI added some debug logging to understand which configuration is being loaded:
@EventListener(ApplicationReadyEvent.class)public void logActiveProfiles(ApplicationReadyEvent event) { ConfigurableApplicationContext context = event.getApplicationContext(); String[] activeProfiles = context.getEnvironment().getActiveProfiles(); System.out.println("Active profiles: " + Arrays.toString(activeProfiles));
ProductService service = context.getBean(ProductService.class); System.out.println("Product service using: " + service.getDatabaseUrl());}Now test again:
$ java -jar myapp.jar --spring.profiles.active=dev,prodActive profiles: [dev, prod]Product service using: prod-dbYou can see that I succeeded to confirm that the last profile in the list overrides the earlier ones.
The reason
I think the key reason for the error is:
-
Profile precedence is left-to-right: When multiple profiles are active in
spring.profiles.active, profiles later in the list take precedence over earlier ones. -
Property files override defaults: Profile-specific properties files (like
application-prod.yml) override properties from the defaultapplication.yml. -
Bean creation order matters: When two beans of the same type exist for different profiles, Spring creates both, but the last profile’s bean “wins” and remains in the context.
Here’s what actually happens:
spring.profiles.active=dev,prod├── dev profile activates│ ├── DevelopmentConfig @Bean created│ └── application-dev.yml properties loaded└── prod profile activates ├── ProductionConfig @Bean created (overwrites dev bean) └── application-prod.yml properties loaded (overwrites dev properties)Summary
In this post, I explained why Spring Boot profile configurations override each other unexpectedly. The key point is that Spring Boot follows a “last wins” precedence rule for multiple active profiles, where profiles later in the spring.profiles.active list override earlier ones.
Final Words + More Resources
My intention with this article was to help others share my knowledge and experience. If you want to contact me, you can contact by email: Email me
Here are also the most important links from this article along with some further resources that will help you in this scope:
Oh, and if you found these resources useful, don’t forget to support me by starring the repo on GitHub!
Comments