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());
}
}