Contents

Spring Boot automatically loads application-{profile}.properties on top of the base application.properties. Profile-specific values override base values.

src/main/resources/ application.properties ← shared / base config application-dev.properties ← development overrides application-test.properties ← test environment application-prod.properties ← production overrides

application-dev.properties:

spring.datasource.url=jdbc:h2:mem:devdb spring.jpa.hibernate.ddl-auto=create-drop logging.level.io.cscode=DEBUG

application-prod.properties:

spring.datasource.url=jdbc:postgresql://prod-db-host:5432/mydb spring.datasource.username=${DB_USER} spring.datasource.password=${DB_PASS} spring.jpa.hibernate.ddl-auto=validate

1. In application.properties (useful for local dev):

spring.profiles.active=dev

2. JVM system property (common in CI scripts):

java -Dspring.profiles.active=prod -jar myapp.jar

3. Environment variable (Kubernetes, Docker, cloud platforms):

SPRING_PROFILES_ACTIVE=prod java -jar myapp.jar

Use @Profile to register a bean only when a specific profile is active — ideal for swapping implementations between environments.

public interface NotificationService { void send(String message); } import org.springframework.context.annotation.Profile; import org.springframework.stereotype.Service; @Service @Profile("dev") // only active in 'dev' profile public class ConsoleNotificationService implements NotificationService { @Override public void send(String message) { System.out.println("[DEV] " + message); } } @Service @Profile("prod") // only active in 'prod' profile public class EmailNotificationService implements NotificationService { @Override public void send(String message) { // send real email via SMTP / SES } }

You can also negate a profile: @Profile("!prod") activates the bean for every profile except prod.

Beans annotated with @Profile("default") are active only when no other profile is active — a safe fallback for local development.

@Service @Profile("default") public class StubPaymentService implements PaymentService { @Override public void charge(Order order) { System.out.println("Stub: charged order " + order.getId()); } }