@Profile, spring.profiles.active, spring.profiles.default, spring.profiles.include, profile groups, profile-specific files, and property precedence.
A profile is a named environment or configuration mode.
For example:
The same Spring Boot application can activate different profiles depending on where it is running.
Imagine this application:
| Environment | Database | Logging | External API |
|---|---|---|---|
| Development | localhost | DEBUG | Sandbox |
| QA | QA DB | INFO | QA API |
| Production | Production DB | WARN/INFO | Production API |
Without profiles, developers often end up changing configuration manually before each deployment.
You can mark a @Component, @Configuration, or @ConfigurationProperties with @Profile to control when it is loaded.
import org.springframework.context.annotation.Configuration;
import org.springframework.context.annotation.Profile;
@Configuration(proxyBeanMethods = false)
@Profile("production")
public class ProductionConfiguration {
// Production-only configuration
}
This configuration is loaded only when the production profile is active.
If production is not active, this configuration is not loaded.
You can use profiles on regular Spring components as well.
@Component
@Profile("dev")
public class DevEmailService implements EmailService {
@Override
public void send(String message) {
System.out.println("DEV EMAIL: " + message);
}
}
@Component
@Profile("production")
public class ProductionEmailService implements EmailService {
@Override
public void send(String message) {
// Send a real email
}
}
Now:
| Active profile | Bean available |
|---|---|
dev | DevEmailService |
production | ProductionEmailService |
A very common pattern is to put several related beans inside a profile-specific configuration class.
@Configuration
@Profile("dev")
public class DevConfig {
@Bean
public PaymentClient paymentClient() {
return new FakePaymentClient();
}
@Bean
public EmailClient emailClient() {
return new ConsoleEmailClient();
}
}
@Configuration
@Profile("production")
public class ProductionConfig {
@Bean
public PaymentClient paymentClient() {
return new RealPaymentClient();
}
@Bean
public EmailClient emailClient() {
return new RealEmailClient();
}
}
Spring Boot uses the spring.profiles.active property to specify active profiles.
spring.profiles.active=dev
spring:
profiles:
active: "dev"
java -jar app.jar --spring.profiles.active=dev
You can activate more than one profile:
spring.profiles.active=dev,hsqldb
This means both dev and hsqldb are active.
Suppose your file contains:
spring.profiles.active=dev
But you start the application with:
java -jar app.jar --spring.profiles.active=production
The command-line value wins because spring.profiles.active follows the normal property-source ordering rules. The highest-precedence source wins.
application.properties can be replaced by a higher-precedence source such as the command line.
If no profile is active, Spring Boot enables a default profile.
The default profile name is:
default
You can change it:
spring.profiles.default=local
Now, when no explicit profile is active, local becomes the default profile.
spring.profiles.default=none
This means no default profile is automatically activated.
| Property | Meaning |
|---|---|
spring.profiles.active | Explicitly chooses profiles to activate. |
spring.profiles.default | Defines what profile is used when no profile is active. |
spring.profiles.active=prod, then prod is active.spring.profiles.active is absent, Spring Boot uses the default profile, which is default unless changed.
spring.profiles.active and spring.profiles.default can only be used in non-profile-specific documents. They cannot be placed inside profile-specific files or documents activated using spring.config.activate.on-profile.
spring.profiles.active inside application-prod.properties or inside a YAML document activated by spring.config.activate.on-profile.
spring.profiles.active=prod #--- spring.config.activate.on-profile=prod spring.profiles.active=metrics
The second document is invalid because it attempts to activate profiles from a profile-activated document.
You can create separate configuration files for each profile.
application.properties application-dev.properties application-qa.properties application-prod.properties
Example base configuration:
spring.application.name=my-api server.port=8080 app.message=Default message
Development:
app.message=Development message app.database-url=jdbc:postgresql://localhost/dev
Production:
app.message=Production message app.database-url=jdbc:postgresql://prod-db/myapp
Suppose:
application.properties application-prod.properties
And:
spring.profiles.active=prod
Properties from the profile-specific configuration can override corresponding values from the base configuration.
You can activate multiple profiles:
spring.profiles.active=prod,metrics
This can be useful when profiles represent separate concerns.
prod → production behaviormetrics → monitoring behaviorSometimes you do not want to replace active profiles. You want to add more profiles.
Use:
spring.profiles.include[0]=common spring.profiles.include[1]=local
YAML:
spring:
profiles:
include:
- "common"
- "local"
Included profiles are added before the profiles activated by spring.profiles.active.
| Property | What it does |
|---|---|
spring.profiles.active | Defines the active profiles. |
spring.profiles.include | Adds additional profiles on top of active profiles. |
spring.profiles.active=production spring.profiles.include[0]=common spring.profiles.include[1]=metrics
The effective profile set includes:
spring.profiles.include is processed for each property source, so normal complex-type list merging rules do not apply.
Like spring.profiles.active, spring.profiles.include can only be used in non-profile-specific documents.
spring.profiles.include inside a profile-specific file or a document activated by spring.config.activate.on-profile.
Sometimes profiles become too fine-grained.
For example:
proddb → production databaseprodmq → production messagingInstead of activating both manually, create a profile group:
spring.profiles.group.production[0]=proddb spring.profiles.group.production[1]=prodmq
YAML:
spring:
profiles:
group:
production:
- "proddb"
- "prodmq"
Now you can simply run:
java -jar app.jar --spring.profiles.active=production
and Spring Boot activates:
spring:
profiles:
group:
production:
- proddb
- prodmq
development:
- devdb
- devtools
Now:
| Active profile | Profiles activated |
|---|---|
production | production + proddb + prodmq |
development | development + devdb + devtools |
spring.profiles.group can only be used in non-profile-specific documents. It cannot be defined inside a profile-specific file or a document activated by spring.config.activate.on-profile.
You can programmatically add profiles before the application runs.
SpringApplication application =
new SpringApplication(MyApplication.class);
application.setAdditionalProfiles("metrics", "local");
application.run(args);
The official documentation also notes that profiles can be activated through Spring's ConfigurableEnvironment interface.
@ConfigurationProperties has a specific profile-related rule.
If configuration properties are scanned automatically, @Profile can be placed directly on the @ConfigurationProperties class.
@ConfigurationProperties("app")
@Profile("production")
public class ProductionProperties {
// ...
}
But if the properties bean is registered through @EnableConfigurationProperties, put @Profile on the configuration class containing @EnableConfigurationProperties.
@Configuration
@Profile("production")
@EnableConfigurationProperties(ProductionProperties.class)
public class ProductionConfig {
}
@Profile belongs on the properties class in every registration style. The placement depends on how the @ConfigurationProperties bean is registered.
Spring Boot validates profile names by default.
Permitted profile names can contain letters, numbers, and characters such as:
They must start and end with a letter or number.
If you need more flexible profile names, you can disable validation:
spring.profiles.validate=false
YAML:
spring:
profiles:
validate: false
This behavior is documented in the current Spring Boot Profiles documentation.
These two concepts are related but different.
| Feature | Purpose | Example |
|---|---|---|
| Profile-specific file | Change property values by environment. | application-prod.properties |
@Profile | Choose which beans/configuration classes are created. | @Profile("prod") |
@Profile = which beans/configuration exist
spring.application.name=my-api app.timeout=30s
app.database-url=jdbc:postgresql://localhost/dev app.logging-level=DEBUG
app.database-url=jdbc:postgresql://qa-db/myapp app.logging-level=INFO
app.database-url=jdbc:postgresql://prod-db/myapp app.logging-level=WARN
Run development:
java -jar app.jar --spring.profiles.active=dev
Run QA:
java -jar app.jar --spring.profiles.active=qa
Run production:
java -jar app.jar --spring.profiles.active=prod
Suppose your application sends notifications.
@Component
@Profile("dev")
public class ConsoleNotificationService
implements NotificationService {
public void send(String message) {
System.out.println(message);
}
}
@Component
@Profile("prod")
public class EmailNotificationService
implements NotificationService {
public void send(String message) {
// Send real email
}
}
Now the application can use the same interface while the implementation changes according to the active profile.
Profiles become especially powerful when combined with externalized configuration.
For example:
application.properties application-prod.properties Environment variable Command-line argument
The final value is determined by Spring Boot's property-source precedence rules.
| Mistake | Correct understanding |
|---|---|
Putting spring.profiles.active inside application-prod.properties. | Active/default profile properties belong in non-profile-specific documents. |
Thinking include replaces active profiles. | include adds profiles. |
| Manually activating every fine-grained profile. | Use a profile group. |
| Using a profile only for property values when bean implementations must change. | Use @Profile on components/configuration. |
| Assuming the default profile runs even when another profile is active. | The default profile is used when no profile is active. |
| Ignoring property precedence. | Higher-precedence sources can replace active profile configuration. |
Putting @Profile on the wrong configuration-properties registration point. | Placement depends on whether scanning or @EnableConfigurationProperties is used. |
dev, qa, staging, prod.@Profile when bean implementations should change.include when common additional profiles should always be added.| Requirement | Use |
|---|---|
| Different property values for dev/prod | Profile-specific files |
| Different bean implementation for dev/prod | @Profile |
| Always add common configuration | spring.profiles.include |
| Group several profiles under one logical name | spring.profiles.group |
| Choose active environment | spring.profiles.active |
| Choose fallback profile | spring.profiles.default |
| Add profiles from Java | setAdditionalProfiles() |
| Need custom profile-name syntax | spring.profiles.validate=false |
@Profile do?@Profile be used?spring.profiles.active?spring.profiles.default?spring.profiles.active be placed inside a profile-specific file?active and include?spring.profiles.group?application-prod.properties and @Profile("prod")?@Profile work with @ConfigurationProperties?application-dev.properties and application-prod.properties.application.properties.@Profile("dev") bean and a @Profile("prod") bean.production profile group containing proddb and prodmq.common and metrics using spring.profiles.include.local.spring.profiles.active cannot be placed inside application-prod.properties.| Concept | Example |
|---|---|
| Activate profile | spring.profiles.active=prod |
| Command-line activation | --spring.profiles.active=prod |
| Default profile | spring.profiles.default=local |
| No default profile | spring.profiles.default=none |
| Add profiles | spring.profiles.include |
| Group profiles | spring.profiles.group |
| Profile-specific properties | application-prod.properties |
| Profile-specific bean | @Profile("prod") |
| Programmatic profiles | setAdditionalProfiles() |
| Disable profile-name validation | spring.profiles.validate=false |
spring.profiles.active → Which profiles should run?spring.profiles.default → Which profile should run if none is active?spring.profiles.include → Add extra profiles.spring.profiles.group → Give a logical name to several profiles.@Profile → Decide which beans/configuration are loaded.application-prod.properties → Change configuration values for production.setAdditionalProfiles() → Add profiles programmatically.