Home/Learn/Spring Boot/Spring Profiles

Spring Profiles

Intermediate
Core & Setup

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

YAML — Profile Files
# 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.

Shell / YAML / Java — Activating Profiles
# 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.

Java — @Profile Bean Registration
// 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 Aria
1

How does Spring Boot resolve the same property key defined in both application.yml and application-prod.yml?

EasyInfosys
2

What is the difference between @Profile and @ConditionalOnProperty?

MediumAmazon
3

How would you configure a different DataSource bean for test vs production environments using profiles?

MediumFlipkart
4

How do you activate multiple profiles simultaneously?

EasyWipro
5

How do you apply a profile in a @SpringBootTest without modifying application.yml?

MediumGoogle

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.

Loading discussion…