Using Spring Boot Profiles to Keep Environment‑Specific Settings Out of Code
Learn how Spring Boot profile‑specific externalized configuration lets you keep environment‑specific properties out of Java code, with a concrete example, verification steps, and cautions about secrets and activation mistakes.
20 Feb 2026, 07:42 UTC

Problem: configuration drift between environments
When a Spring Boot application is promoted from a developer laptop to a test server and finally to production, hard‑coded values such as database URLs, feature flags, or logging levels often diverge. Manual edits increase the risk of deploying the wrong setting, and the same codebase ends up containing multiple "if‑else" blocks just to pick a value.
Thesis: let Spring Boot’s profile‑specific externalized configuration handle the switch
Spring Boot loads application.properties (or application.yml) first, then overlays any application-{profile}.properties files that match the active profile(s). Later files win, so you can keep common settings in the base file and override only what changes per environment—without touching Java code.
How the loading order works
- Spring Boot reads
application.properties(or YAML). - If one or more profiles are active, it reads
application-{profile}.propertiesfor each, in the order they are activated. - Properties from later files replace earlier ones; unset base properties remain in effect.
Profiles can be activated in several ways:
spring.profiles.active=devinapplication.properties- Command line:
java -jar app.jar --spring.profiles.active=prod - Environment variable:
SPRING_PROFILES_ACTIVE=test - Servlet init parameter (for traditional WAR deployments)
Worked example: toggling a greeting service
Suppose we want a different greeting shown in the UI depending on the environment.
1. Base configuration (src/main/resources/application.properties)
# Shared settings
server.port=8080
app.greeting=Hello from undefined environment
2. Development overlay (src/main/resources/application-dev.properties)
# Override only what changes
app.greeting=Hello from Dev
3. Production overlay (src/main/resources/application-prod.properties)
app.greeting=Hello from Production
4. Activating a profile
Start the jar with the dev profile:
java -jar myapp.jar --spring.profiles.active=dev
5. Verifying the result
If Spring Boot Actuator is on the classpath, hit /actuator/env and look for app.greeting; it should show "Hello from Dev". Without Actuator, you can expose the value through a simple bean:
@RestController public class GreetingController { @Value("${app.greeting}") private String greeting; @GetMapping("/greeting") public String greeting() { return greeting; } }Calling
GET /greetingreturns the dev message. Switching to--spring.profiles.active=prodchanges the response without any code rebuild.Trade‑offs and limitations
- Layering, not replacement: If a property is omitted in the profile file, the base value stays active. Forgetting to override a setting can leave a test value in production.
- Secret leakage: Storing passwords or API keys in plain
application-{profile}.propertiesrisks accidental commits. Use Spring Cloud Config Server with encryption, Vault, or Docker/Kubernetes secrets for production credentials. - Profile activation mistakes: Activating the wrong profile (e.g.,
devon prod) points the app at a test database or external service. Guard against this by making the active profile explicit in startup scripts or CI pipelines, and by checking/actuator/envon startup. - Logging configuration: Changing log levels via
application-{profile}.propertiesworks only for properties understood by Logback/Spring Boot’s logging system. For advanced logback‑spring.xml tweaks, you need<springProfile>blocks inside the XML.
Actionable closing
To adopt profile‑specific configuration safely:
- Keep all shared settings in
application.properties. - Create a profile file for each environment (
dev,test,prod) and override only the values that differ. - Activate the profile via an explicit mechanism that cannot be overridden by an accidental environment variable—prefer a command‑line argument or a dedicated startup script.
- Verify at startup: check the logged "Active Profiles" line or hit
/actuator/envto confirm the expected property values. - For secrets, replace plain values with placeholders and resolve them from a secret manager at runtime.
By letting Spring Boot’s profile layering do the work, you eliminate environment‑specific code branches and reduce the risk of deploying the wrong configuration.
0 replies
A thoughtful contribution can make all the difference. Be the first to share one.