spring.profiles.active is a Spring Boot property that tells the framework which configuration profile to load at startup. Set it once, and Spring automatically picks the right application-{profile}.yml, registers the right beans, and skips everything else. The result: one codebase, zero environment-specific hacks, clean deployments to dev, staging, and production.
Quick answer
- What it does:
spring.profiles.activetells Spring Boot which profile or profiles to activate at startup. - Best for local default: set it in
application.propertiesorapplication.yml. - Best for Docker, Kubernetes, and CI/CD: use
SPRING_PROFILES_ACTIVE. - Best for one-off runs: use
--spring.profiles.active=...on the command line. - Most important rule: the highest-precedence property source wins.
- Common mistake: putting
spring.profiles.activeinside a profile-specific document — that is invalid.
The most common place to set it is application.properties:
spring.profiles.active=development
Or activate it at runtime without touching any file:
java -jar myapp.jar --spring.profiles.active=production
Key Benefits at a Glance
- Environment-Specific Configuration: Switch between dev, test, and prod settings without changing application code.
- Improved Security: Keep production credentials isolated from development environments, reducing the risk of accidental data leaks.
- Faster Development Cycles: Use lightweight in-memory databases locally; switch to real infrastructure only in production.
- Streamlined CI/CD: Let pipelines inject profiles via environment variables — no file edits, no merge conflicts.
- Easier Maintenance: One property change per environment instead of scattered conditional logic throughout your code.
Key takeaways
- Set
spring.profiles.activevia config file, environment variable, command line, or code - Multiple profiles can be active simultaneously using comma-separated values
- Profile-specific files automatically override the base config
- The highest-precedence property source wins
- Profile groups help simplify large multi-profile setups
Table of contents
- Understanding Spring profiles: core concepts and benefits
- The spring.profiles.active property: detailed explanation
- Methods for setting active profiles
- Where to set spring.profiles.active in real projects
- Command line activation
- Environment variables and system properties
- Programmatic activation
- Configuration file approaches
- Profile activation priority
- Using spring.profiles.include
- Profile-specific configuration files
- Multi-document YAML files
- Real-world implementation examples
- Default profile and its purpose
- Spring Boot profile integration
- Profile groups in Spring Boot
- Best practices and common pitfalls
- Debugging and troubleshooting profile issues
- Advanced profile techniques
- Frequently Asked Questions
Understanding Spring profiles: core concepts and benefits
A Spring profile is a named set of bean definitions and configuration properties that activates together. When you mark a bean or configuration class with @Profile("production"), Spring only registers it when that profile is active. Everything else is ignored.
@Configuration
@Profile("development")
public class DevMailConfig {
@Bean
public JavaMailSender mailSender() {
// Points to a local MailHog instance, never sends real email
...
}
}
- Profile names are arbitrary identifiers that should stay clean and descriptive
- Multiple profiles can be active at once
- Profiles work at both the bean level (
@Profile) and the config file level (application-{profile}.yml) - The
defaultprofile activates automatically when nothing else is set
By default, Spring Boot validates profile names. Current documentation allows profile names to contain letters, numbers, and these characters: -, _, ., +, and @. A profile name must start and end with a letter or number. This is stricter than “any arbitrary string”, and it helps avoid parsing problems.
- Good examples:
dev,production,feature-x,redis_cache,prod.eu - Avoid spaces and messy naming conventions
- If you really need looser rules, Spring Boot supports
spring.profiles.validate=false
The practical payoff is obvious: a developer can run the app locally with lightweight infrastructure, while the production container injects hardened configuration through the active profile. Same jar, completely different runtime behavior.
The spring.profiles.active property: detailed explanation
The spring.profiles.active property accepts a comma-separated list of profile names. Spring resolves it early in the startup sequence, before bean registration begins, so profile-based bean loading, configuration file selection, and auto-configuration all happen with the final active profile list already known.
“You can use a spring.profiles.active Environment property to specify which profiles are active.”
— Spring Boot Documentation
Source link
- Spring resolves
spring.profiles.activefrom all available property sources - The highest-precedence source wins
- Profile-specific config files are loaded and merged over the base config
- Beans annotated with
@Profileare registered or skipped accordingly - Auto-configuration adapts to the active profiles
Important restriction
spring.profiles.activecan only be defined in a non-profile-specific document.- The same rule also applies to
spring.profiles.default,spring.profiles.include, andspring.profiles.group. - Do not place these inside
application-production.ymlor inside YAML sections activated byspring.config.activate.on-profile. - If you do, the configuration is invalid and Spring Boot will not treat it as a proper profile activation setup.
# ✅ valid: non-profile-specific document
spring:
profiles:
active: production
---
# ❌ invalid: profile-specific document must not set spring.profiles.active
spring:
config:
activate:
on-profile: production
profiles:
active: metrics
| Value | Result |
|---|---|
spring.profiles.active=dev | Activates the dev profile |
spring.profiles.active=dev,h2 | Activates both dev and h2 |
spring.profiles.active=production,redis | Activates production and redis |
| (not set) | Activates the default profile |
Methods for setting active profiles
Spring supports several ways to activate profiles. Each has its own place depending on whether you are running locally, inside a container, or through a CI/CD pipeline.
| Method | Precedence | Best for | Portability |
|---|---|---|---|
| Command Line | Highest | Dev / quick testing | Low |
| Environment Variables | High | Docker / Kubernetes / CI | High |
| System Properties | Medium | App servers / controlled JVM startup | Medium |
| Configuration Files | Lowest | Defaults / fallback | High |
Where to set spring.profiles.active in real projects
| Environment | Recommended approach | Why |
|---|---|---|
| Local development | application.properties or IDE run config | Simple, predictable default for every developer |
| CI/CD pipeline | Environment variable | No code changes, easy injection per stage |
| Docker / Kubernetes | SPRING_PROFILES_ACTIVE | Matches container-native config patterns |
| One-off debugging | Command-line argument | Highest precedence, easiest temporary override |
Command line activation
The command line gives you the highest precedence and zero file changes. Two syntaxes work:
# JVM system property
java -Dspring.profiles.active=dev,hsqldb -jar myapplication.jar
# Spring Boot argument style
java -jar myapplication.jar --spring.profiles.active=production,mysql
Both are equivalent in effect. The Spring Boot argument style is slightly more natural in Boot-only applications, and it works especially well for one-off debugging and local testing.
Environment variables and system properties
The environment variable SPRING_PROFILES_ACTIVE is the standard way to inject profiles in containers and CI pipelines. Spring Boot maps it automatically through relaxed binding.
# Unix/Linux/macOS
export SPRING_PROFILES_ACTIVE=production,redis
java -jar myapplication.jar
# Windows Command Prompt
set SPRING_PROFILES_ACTIVE=production,redis
java -jar myapplication.jar
# Windows PowerShell
$env:SPRING_PROFILES_ACTIVE="production,redis"
java -jar myapplication.jar
In Docker Compose, pass it directly in the service definition:
services:
app:
image: myapp:latest
environment:
- SPRING_PROFILES_ACTIVE=production,redis
ports:
- "8080:8080"
In Kubernetes, inject it in the pod spec:
env:
- name: SPRING_PROFILES_ACTIVE
value: "production,redis"
System properties are an alternative when environment variables are restricted:
System.setProperty("spring.profiles.active", "development,h2");
Programmatic activation
For cases where the profile depends on runtime logic, activate it before the application context starts:
@SpringBootApplication
public class Application {
public static void main(String[] args) {
SpringApplication app = new SpringApplication(Application.class);
app.setAdditionalProfiles(determineActiveProfile());
app.run(args);
}
private static String determineActiveProfile() {
return System.getProperty("deployment.environment", "development");
}
}
setAdditionalProfiles() adds profiles to the application before startup rather than replacing every other possible source. Use it when your application needs to activate supporting profiles programmatically, not when you want to override external configuration supplied by operations or CI/CD.
For tests, prefer @ActiveProfiles instead of setting system properties manually. It is cleaner and resets automatically with the test context.
Configuration file approaches
Setting the profile in a config file provides a reliable default. This is ideal for establishing a safe local-development baseline so the app starts without any external arguments.
| Format | Readability | Complex structures | Recommended for |
|---|---|---|---|
| Properties | Good | Limited | Simple configs, legacy projects |
| YAML | Excellent | Excellent | Most Spring Boot projects |
# application.properties
spring.profiles.active=development
# application.yml
spring:
profiles:
active: development
Keep this value set to your safe local profile in version control. Override it via environment variable or command line in automated environments.
Profile activation priority
When the same property is set in multiple places, Spring applies a strict precedence order. The highest-precedence source wins completely.
- Command line arguments (
--spring.profiles.activeor-Dspring.profiles.active) - Environment variables (
SPRING_PROFILES_ACTIVE) - System properties set programmatically (
System.setProperty(...)) - Configuration files (
application.properties/application.yml) - Default profile — activates automatically if nothing else is set
spring.profiles.activeis not merged across property sources — the highest-precedence value wins.- If you need to add profiles on top of the active ones instead of replacing them, use
spring.profiles.include.
A common debugging trap is seeing an unexpected profile even though the properties file says something else. In practice, that usually means an environment variable or CLI argument already overrode it.
- If
SPRING_PROFILES_ACTIVE=productionis set in the environment andspring.profiles.active=devis inapplication.properties,productionwins. - Command-line arguments override even environment variables — useful for simulating production-like scenarios locally.
Using spring.profiles.include
Sometimes you do not want to replace the active profile list — you want to add profiles on top of it. That is what spring.profiles.include is for.
spring:
profiles:
include:
- common
- local
With this setup, common and local are added before the explicitly active profiles. This is useful for shared infrastructure profiles such as common logging, shared metrics, or local development support.
- Use
spring.profiles.activewhen you want to choose profiles explicitly - Use
spring.profiles.includewhen you want to add supporting profiles automatically
Profile-specific configuration files
Spring Boot automatically loads application-{profile}.properties or application-{profile}.yml when a profile is active. Profile-specific files are loaded after the base config and override matching keys.
src/main/resources/
├── application.yml
├── application-development.yml
├── application-testing.yml
├── application-staging.yml
└── application-production.yml
- The base file always loads first
- The profile-specific file loads second and overrides matching keys
- Properties not present in the profile-specific file fall back to the base file
- With multiple active profiles, later files win conflicts
Keep the base file lean. Only properties that are truly identical across all environments belong there.
Multi-document YAML files
Instead of multiple files, you can consolidate profile-specific configuration into a single application.yml using YAML document separators.
| Approach | Pros | Cons |
|---|---|---|
| Separate files | Clear separation, easy review per environment | More files to manage |
| Multi-document YAML | Single file, side-by-side comparison | Gets messy when profiles multiply |
# Applies to all profiles
server:
port: 8080
logging:
level:
root: INFO
---
spring:
config:
activate:
on-profile: development
datasource:
url: jdbc:h2:mem:devdb
username: dev
password: dev
logging:
level:
com.example: DEBUG
---
spring:
config:
activate:
on-profile: production
datasource:
url: jdbc:mysql://prod-db:3306/proddb
username: ${DB_USERNAME}
password: ${DB_PASSWORD}
logging:
level:
com.example: WARN
In Spring Boot 2.4+, use spring.config.activate.on-profile for YAML document activation. It is the modern and recommended form.
Real-world implementation examples
The most common real-world profile scenarios are database configuration, feature toggles, and logging behavior.
Database configuration:
@Configuration
@Profile("development")
public class DevelopmentDatabaseConfig {
@Bean
@Primary
public DataSource dataSource() {
return new EmbeddedDatabaseBuilder()
.setType(EmbeddedDatabaseType.H2)
.addScript("schema.sql")
.addScript("test-data.sql")
.build();
}
}
@Configuration
@Profile("production")
public class ProductionDatabaseConfig {
@Bean
@Primary
public DataSource dataSource() {
HikariConfig config = new HikariConfig();
config.setJdbcUrl("jdbc:mysql://prod-db:3306/proddb");
config.setUsername("${DB_USERNAME}");
config.setPassword("${DB_PASSWORD}");
config.setMaximumPoolSize(20);
return new HikariDataSource(config);
}
}
Feature toggles:
@Controller
@Profile("feature-new-ui")
public class NewDashboardController {
@GetMapping("/dashboard")
public String newDashboard(Model model) {
return "new-dashboard";
}
}
@Controller
@Profile("!feature-new-ui")
public class LegacyDashboardController {
@GetMapping("/dashboard")
public String legacyDashboard(Model model) {
return "legacy-dashboard";
}
}
Logging:
# application-development.yml
logging:
level:
com.example: DEBUG
org.springframework.web: DEBUG
# application-production.yml
logging:
level:
com.example: WARN
root: ERROR
Profile-aware HTTP responses follow the same idea: detailed diagnostics in development, safer output in production. See ResponseEntity in Spring Boot. When structuring data between layers, DTOs keep your API contracts clean across all profiles — see What is DTO in Spring Boot.
Default profile and its purpose
The default profile is a safety net. Spring activates it automatically when no other profiles are set.
@Configuration
@Profile("default")
public class DefaultConfiguration {
@Bean
public DataSource dataSource() {
return new EmbeddedDatabaseBuilder()
.setType(EmbeddedDatabaseType.H2)
.build();
}
@Bean
public CacheManager cacheManager() {
return new ConcurrentMapCacheManager();
}
}
You can also rename the default profile using spring.profiles.default:
spring.profiles.default=local-development
In practice, the default profile should represent “what a developer gets on first clone” — safe local dependencies, no production secrets, no real external side effects.
Spring Boot profile integration
Spring Boot adds a few important features on top of base Spring profile support, especially for configuration files and deployment workflows.
| Feature | Traditional Spring | Spring Boot |
|---|---|---|
| YAML multi-document | Basic | Full support with on-profile |
| Profile groups | Not available | Built-in |
| Maven / Gradle integration | Manual | Simple to wire |
| Auto-configuration awareness | Manual | Profile-aware out of the box |
| Actuator visibility | Not built in | /actuator/env helps inspect config |
Maven integration:
<profiles>
<profile>
<id>development</id>
<properties>
<spring.profiles.active>dev,h2</spring.profiles.active>
</properties>
</profile>
<profile>
<id>production</id>
<properties>
<spring.profiles.active>prod,mysql</spring.profiles.active>
</properties>
</profile>
</profiles>
Gradle integration:
bootRun {
args = ["--spring.profiles.active=${project.findProperty('profile') ?: 'development'}"]
}
// Run with: ./gradlew bootRun -Pprofile=production
Profile groups in Spring Boot
Profile groups let you activate multiple profiles with one logical name. This is cleaner than forcing operators to remember long comma-separated lists.
spring:
profiles:
group:
production: "proddb,prodcache,prodlogging"
development: "devdb,devcache,devlogging,debug"
testing: "testdb,testcache,mockedservices"
Groups can also be composed for larger setups:
spring:
profiles:
group:
database-dev: "h2,flyway"
database-prod: "mysql,flyway"
cache-dev: "simple-cache"
cache-prod: "redis,redis-cluster"
full-dev: "database-dev,cache-dev,debug"
full-prod: "database-prod,cache-prod,monitoring"
Profile groups are especially useful when environments activate multiple infrastructure capabilities together and you want a single, memorable top-level profile such as production.
Best practices and common pitfalls
- Use descriptive names instead of ambiguous shortcuts when it improves clarity
- Keep profile-specific files minimal — only override what really differs
- Never commit real production credentials, even in production files
- Use placeholders like
${DB_PASSWORD}for secrets - Document which profiles are expected in each environment
| Pitfall | Symptom | Fix |
|---|---|---|
| Profile not activating | Default config used, unexpected beans | Check precedence — another property source may be overriding it |
| Wrong config loaded | App connects to wrong database | Verify file naming: application-dev.yml, not application_dev.yml |
| Multiple profiles conflict | Bean creation errors or ambiguity | Review @Profile usage and add @Primary where appropriate |
| Profile typo | Silent fallback to default behavior | Inspect active profiles via logs or Actuator |
| Production profile in dev | Local machine hits real DB or sends real emails | Commit a safe local default and override only in deployment |
Debugging and troubleshooting profile issues
- Enable debug logging for Spring environment processing
- Check active profiles via
Environment.getActiveProfiles() - Review startup logs for config loading order
- Test each profile in isolation before combining them
- Use Actuator to inspect the final resolved configuration
Enable useful debug logging:
logging.level.org.springframework.core.env=DEBUG
logging.level.org.springframework.boot.context.config=DEBUG
Verify active profiles programmatically:
@Component
public class ProfileVerificationComponent {
@Autowired
private Environment environment;
@PostConstruct
public void verifyProfiles() {
log.info("Active profiles: {}", Arrays.toString(environment.getActiveProfiles()));
log.info("Default profiles: {}", Arrays.toString(environment.getDefaultProfiles()));
}
}
In non-production environments, the Actuator /actuator/env endpoint is one of the best tools for debugging why a profile or property value resolved the way it did.
management:
endpoints:
web:
exposure:
include: env,health,info
Advanced profile techniques
The @Profile annotation supports boolean expressions using & (AND), | (OR), and ! (NOT). This lets you describe precise activation rules without inventing too many profile names.
@Configuration
@Profile("production & !debug & (mysql | postgresql)")
public class ProductionDatabaseConfig {
...
}
@Component
@Profile("!test")
public class ExternalNotificationService {
...
}
For custom auto-configuration libraries, combine @ConditionalOnProperty with @Profile when both environment and capability checks matter:
@Configuration
@Profile("metrics")
@ConditionalOnClass(PrometheusMeterRegistry.class)
public class MetricsAutoConfiguration {
@Bean
@ConditionalOnMissingBean
public MeterRegistry meterRegistry() {
return new PrometheusMeterRegistry(PrometheusConfig.DEFAULT);
}
}
Do not try to switch profiles dynamically after the application context is already running. If you need dynamic behavior at runtime, use feature flags or @ConditionalOnProperty within a stable profile setup instead.
Why this matters beyond one property: developers who understand spring.profiles.active usually design cleaner deployment pipelines, safer secrets handling, better local-dev setups, and more reliable production releases. In real Spring Boot work, profiles are part of a bigger skill set: configuration architecture, environment isolation, observability, and deployment discipline.
More Spring Boot guides
- Mastering ResponseEntity in Spring Boot — control HTTP status codes, headers, and response bodies per environment
- What is DTO in Spring Boot — keep your API layer clean with Data Transfer Objects
- Java: pass function as parameter — write more flexible, reusable Spring service methods
- Static vs non-static in Java — understand when to use static helpers in Spring projects
- Java OutputStream to String — handle stream-based data in Spring controllers and services
Frequently Asked Questions
spring.profiles.active is a Spring Boot property that specifies which profiles are active for the current application run. When set, Spring loads the matching configuration files and registers only the beans that match those profiles.
Use either java -jar app.jar --spring.profiles.active=production or java -Dspring.profiles.active=production -jar app.jar. Both work, and command-line values have the highest precedence.
spring.profiles.active explicitly sets which profiles are active. spring.profiles.default defines which profile activates only when nothing else is active.
Yes. Use a comma-separated list such as spring.profiles.active=production,redis,monitoring. All listed profiles become active together.
Use the environment variable SPRING_PROFILES_ACTIVE. Spring Boot automatically maps it to spring.profiles.active.
Create files such as application-dev.yml or application-production.yml. Spring Boot loads the base file first, then overlays the profile-specific file for the active profile.
No. spring.profiles.active must be defined only in non-profile-specific documents. It cannot be placed in profile-specific files or YAML sections activated with spring.config.activate.on-profile.
spring.profiles.active explicitly selects which profiles are active. spring.profiles.include adds extra profiles on top of the active ones. Use active to choose, and include to supplement.




