Profiles and Environments
What is a Profile?
A Spring profile is a named configuration set. Profiles allow you to maintain different property files and bean definitions for different environments without changing code.
When a profile is active, Spring Boot loads
the corresponding application-{profile}.yml file,
overriding the base application.yml.
Active Profiles in This Project
(Default) — Local Development
When: No profile is explicitly set; used locally when developing
Configuration file:
application.yml only
Database: Requires environment setup -
Expects DB_URL, DB_USER,
DB_PASS environment variables - Can be PostgreSQL
or Oracle, depending on your setup
Demo Mode: Enabled by default
(APP_DEMO_READONLY=true)
Activation:
# No SPRING_PROFILES_ACTIVE set
mvn spring-boot:run
# Or explicitly empty
export SPRING_PROFILES_ACTIVE=""test
When: Running tests in CI/CD pipeline or locally
Configuration file:
application-test.yml + base
application.yml
Database: H2 in-memory (Oracle-compatible
mode) - Fast, isolated, requires no setup - Recreated for each
test run (create-drop mode)
Logging: SQL statements logged
(show-sql: true)
Demo Mode: Can be overridden per test
Activation:
# Maven
mvn clean test
# Environment variable
export SPRING_PROFILES_ACTIVE="test"
mvn spring-boot:run
# Java system property
java -Dspring.profiles.active=test -jar app.jar
# Docker
docker run -e SPRING_PROFILES_ACTIVE=test myapp:latestprod
When: Production deployment (Fly.io, cloud, or production server)
Configuration file:
application-prod.yml + base
application.yml
Database: Oracle with production-grade
connection pooling - Requires DB_URL,
DB_USER, DB_PASS from secure
environment - Connection pool tuned for low-memory
environments
Logging: Only INFO level and above
(logging.level.root: INFO)
Security: - SQL logging disabled
(show-sql: false) - No internal endpoint details
exposed
(management.endpoint.health.show-details: never) -
Secure cookies enforced (secure: true)
Demo Mode: Usually disabled in production
(APP_DEMO_READONLY=false)
Activation:
# Fly.io (fly.toml)
[env]
SPRING_PROFILES_ACTIVE = "prod"
# Docker
docker run -e SPRING_PROFILES_ACTIVE=prod myapp:latest
# Kubernetes
apiVersion: v1
kind: Pod
spec:
containers:
- name: app
env:
- name: SPRING_PROFILES_ACTIVE
value: "prod"How Spring Selects the Active Profile
Environment variable
SPRING_PROFILES_ACTIVE(highest priority)export SPRING_PROFILES_ACTIVE="prod"Java system property
java -Dspring.profiles.active=prod -jar app.jarapplication.yml
spring.profiles.activespring: profiles: active: testDefault (if none set): Use base
application.ymlonly
⚠️ Important: Never hardcode
spring.profiles.active in
application.yml. Let environment variables control
which profile is used.
Profile Comparison
| Aspect | (Default) | test | prod |
|---|---|---|---|
| Database | PostgreSQL/Oracle (manual setup) | H2 in-memory | Oracle (Autonomous DB) |
| Configuration | application.yml |
application-test.yml |
application-prod.yml |
| SQL Logging | Enabled (DEBUG) | Enabled (DEBUG) | Disabled |
| Show SQL | true | true | false |
| DDL Auto | none | create-drop | update |
| Demo Mode | true (default) | true (default) | true (usually) |
| Log Level | DEBUG for frameworks | DEBUG for frameworks | INFO only |
| Health Endpoint | Shows all details | Shows all details | Never |
| Connection Pool | Default | N/A (H2) | Tuned for Oracle |
Configuration Precedence
When Spring Boot starts, properties are loaded in this order (first match wins):
1. Environment Variables
2. application-{profile}.yml
3. application.yml
4. Java defaults (@ConfigurationProperties)
Example: Database URL
Query: What is spring.datasource.url?
1. Is DB_URL env var set? → Use it (highest priority)
Example: export DB_URL="jdbc:oracle:thin:@prod.db.com:1521/xe"
2. Is the active profile "prod"? Check application-prod.yml
(application-prod.yml also references ${DB_URL}, so env var wins anyway)
3. Check application.yml
spring.datasource.url: ${DB_URL} ← Still references env var
4. Java default: oracle.jdbc.OracleDriver (just the driver class)
← No default for URL; the property is required
Profile-Specific Sections in application.yml
You can also add profile-specific properties
within application.yml using
--- separator:
# Base config (all profiles)
spring:
jpa:
show-sql: true
---
# Only when prod profile is active
spring:
config:
activate:
on-profile: prod
jpa:
show-sql: falseHowever, dedicated files are cleaner and are
used in this project: - application-prod.yml -
application-test.yml
Selecting Profiles for Different Scenarios
Local Development
# 1. No profile (uses default application.yml)
mvn spring-boot:run
# 2. With test profile (for testing locally with H2)
export SPRING_PROFILES_ACTIVE="test"
mvn spring-boot:run
# 3. With prod profile (for testing prod config locally)
# Note: You'll need actual DB credentials
export SPRING_PROFILES_ACTIVE="prod"
export DB_URL="jdbc:oracle:thin:@localhost:1521/xe"
export DB_USER="..."
export DB_PASS="..."
mvn spring-boot:runContinuous Integration (GitHub Actions)
# .github/workflows/test.yml
name: Tests
on: [push]
jobs:
test:
runs-on: ubuntu-latest
steps:
- uses: actions/checkout@v3
- name: Run Tests
env:
SPRING_PROFILES_ACTIVE: test # H2 DB, fast, isolated
run: mvn clean testDocker Deployment
# Dockerfile
FROM maven:3.9-eclipse-temurin-17 AS build
WORKDIR /app
COPY . .
RUN mvn clean package -DskipTests
FROM eclipse-temurin:17-jre
COPY --from=build /app/target/inventory-service-*.jar app.jar
ENTRYPOINT ["java", "-jar", "/app.jar"]# Build and run with prod profile
docker build -t inventory-service .
docker run \
-e SPRING_PROFILES_ACTIVE=prod \
-e DB_URL="jdbc:oracle:thin:@oracle.db.example.com:1521/xe" \
-e DB_USER="admin" \
-e DB_PASS="***" \
inventory-service:latestFly.io Deployment
# fly.toml
app = "inventoryservice"
primary_region = "fra"
[env]
SPRING_PROFILES_ACTIVE = "prod"
APP_DEMO_READONLY = "true"
APP_FRONTEND_BASE_URL = "https://inventoryservice.fly.dev"
[[services]]
internal_port = 8081Secrets are set separately:
fly secrets set DB_URL="jdbc:oracle:thin:@..." \
DB_USER="admin" \
DB_PASS="***" \
SPRING_SECURITY_OAUTH2_CLIENT_REGISTRATION_GOOGLE_CLIENT_ID="..." \
SPRING_SECURITY_OAUTH2_CLIENT_REGISTRATION_GOOGLE_CLIENT_SECRET="..."Troubleshooting Profile Issues
Q: How do I know which profile is active?
A: Check the logs on startup:
The following profiles are active: prod
Or print it programmatically:
@Component
public class ProfileLogger {
@Autowired
private Environment env;
@PostConstruct
public void logProfiles() {
String[] profiles = env.getActiveProfiles();
System.out.println("Active profiles: " + Arrays.toString(profiles));
}
}Q: My config isn’t being loaded. What’s wrong?
A: Check priority order:
- Is the environment variable set? (Check
echo $DB_URL) - Is the profile-specific file correct?
(Check
application-{profile}.yml) - Is the profile active? (Check
SPRING_PROFILES_ACTIVE) - Is the property name spelled correctly? (Hyphens vs underscores matter)
Q: I can’t connect to the database. What profile should I use?
- Test mode (
testprofile) → Use H2, no setup needed - Local dev (default) → Set
DB_URL,DB_USER,DB_PASSenv vars - Production (
prodprofile) → Use Oracle with proper credentials
Related Documentation
- Application Configuration Files
- Database and Oracle Wallet
- Deployment Docs — For environment-specific setup