Skip to content

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:

Terminal window
$ java -jar myapp.jar --spring.profiles.active=dev,prod
2026-02-22 11:45:15.234 INFO --- [ main] c.m.m.p.ProductService : Product service initialized with prod configuration
2026-02-22 11:45:15.235 INFO --- [ main] c.m.m.p.ProductService : Database URL: jdbc:postgresql://prod-db:5432/mydb

But 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
@Configuration
public 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:

Terminal window
$ java -jar myapp.jar --spring.profiles.active=dev,prod
2026-02-22 11:45:15.234 INFO --- [ main] c.m.m.p.ProductService : Product service initialized with prod configuration

The service is using the prod database URL instead of the dev one.

How to solve it?

I tried changing the profile order:

Terminal window
$ java -jar myapp.jar --spring.profiles.active=prod,dev

But I still get the same result - prod configuration wins.

Then I checked the properties files:

application-dev.yml
spring:
datasource:
url: jdbc:postgresql://dev-db:5432/mydb
# application-prod.yml
spring:
datasource:
url: jdbc:postgresql://prod-db:5432/mydb

I 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:

Terminal window
$ java -jar myapp.jar --spring.profiles.active=dev,prod
Active profiles: [dev, prod]
Product service using: prod-db

You 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:

  1. 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.

  2. Property files override defaults: Profile-specific properties files (like application-prod.yml) override properties from the default application.yml.

  3. 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