Spring Profiles
IntermediateProfiles separate configuration per environment (dev, test, prod); beans annotated with @Profile or properties suffixed -dev.yml are activated selectively.
Overview
Spring Profiles provide a mechanism for separating parts of your application configuration and making them available only in certain environments. A profile is simply a named group of beans and properties. You can use profiles to vary the datasource between local development and production, swap a real Stripe payment client for a mock in tests, or activate debug logging only in dev. The active profile is set at runtime — not baked into the JAR — which keeps the same build artefact deployable across all environments. This is a core 12-Factor App principle: externalise environment-specific configuration.
Profile-Specific Properties Files
The simplest way to use profiles is property file naming conventions. Spring Boot automatically loads `application-{profile}.yml` (or `.properties`) when that profile is active. Common files:
- `application.yml` — shared defaults across all environments - `application-dev.yml` — local development overrides - `application-test.yml` — test-specific (in-memory H2, mocked services) - `application-prod.yml` — production (real DB, secrets from vault)
Properties in `application-{profile}.yml` override the same keys in `application.yml`. Multiple profiles can be active simultaneously — later ones override earlier ones.
# application.yml — shared defaults
spring:
application:
name: order-service
jpa:
show-sql: false
logging:
level:
root: INFO
---
# application-dev.yml — local dev overrides
spring:
datasource:
url: jdbc:h2:mem:devdb
driver-class-name: org.h2.Driver
jpa:
show-sql: true # override: show SQL locally
logging:
level:
com.example: DEBUG # verbose logging in dev
---
# application-prod.yml — production
spring:
datasource:
url: ${DB_URL} # injected from env var / Kubernetes Secret
username: ${DB_USER}
password: ${DB_PASS}Activating Profiles
Profiles are activated at runtime, not in code. Priority order (highest wins): 1. `SPRING_PROFILES_ACTIVE` environment variable (K8s, Docker) 2. `spring.profiles.active` JVM system property (`-Dspring.profiles.active=prod`) 3. `spring.profiles.active` in `application.yml` (lowest priority, for development defaults)
Activate multiple profiles with a comma-separated list: `dev,localdb`. The `spring.profiles.default` property sets a fallback profile when none is explicitly activated.
# 1. Environment variable (Kubernetes ConfigMap / Docker)
SPRING_PROFILES_ACTIVE=prod
# 2. JVM system property
java -Dspring.profiles.active=prod -jar app.jar
# 3. application.yml default (useful for local dev)
# application.yml
spring:
profiles:
default: dev # use dev profile if nothing else is set
# 4. Maven / Gradle test profile (CI)
mvn test -Dspring.profiles.active=test
# 5. Programmatic check (testing)
@SpringBootTest
@ActiveProfiles("test")
class OrderServiceTest { }@Profile on Beans — Conditional Registration
@Profile on a @Bean or @Component registers it only when the specified profile is active. This is the idiomatic way to swap implementations between environments — e.g., a real email service in prod and a no-op stub in test.
// Real implementation — only in prod
@Component
@Profile("prod")
public class SmtpEmailService implements EmailService {
@Override
public void send(String to, String subject, String body) {
// real SMTP via JavaMailSender
}
}
// Stub — active in dev and test
@Component
@Profile({"dev", "test"})
public class NoOpEmailService implements EmailService {
@Override
public void send(String to, String subject, String body) {
log.info("STUB: email to {} — {}", to, subject); // no real email sent
}
}
// Negative profile — active when prod is NOT active
@Component
@Profile("!prod")
public class MockPaymentGateway implements PaymentGateway { }Key Points to Remember
- 1Profile-specific files follow the naming convention `application-{profile}.yml`; they override keys in the base `application.yml`.
- 2Set `SPRING_PROFILES_ACTIVE` env var for production/K8s deployments — never hardcode the active profile in application.yml for prod.
- 3Multiple profiles can be active simultaneously: `SPRING_PROFILES_ACTIVE=prod,datadog`.
- 4@Profile on a @Bean or @Component registers it only when the profile matches; use `!prod` for "active in all non-prod environments".
- 5@ActiveProfiles("test") in test classes activates a profile just for that test class without changing JVM arguments.
- 6Profiles do not need to match environment names — you can create profiles for features: `spring.profiles.active=billing-v2`.
Interview Questions
Sign in to ask AriaHow does Spring Boot resolve the same property key defined in both application.yml and application-prod.yml?
What is the difference between @Profile and @ConditionalOnProperty?
How would you configure a different DataSource bean for test vs production environments using profiles?
How do you activate multiple profiles simultaneously?
How do you apply a profile in a @SpringBootTest without modifying application.yml?
Ask Aria about Spring Profiles
Your personal AI tutor — ask anything about this concept
Revision Status
Personal Notes
Sign in to save personal notes for this topic.
Discussion
Sign in to join the discussion.