Spring Boot Profiles: Managing Multiple Environments Like a Pro

Learn how to manage multiple environments in Spring Boot using profiles, properties, and YAML configurations

When developing enterprise applications with Spring Boot, managing multiple environments is a necessity. You need different configurations for development, testing, staging, and production, but hardcoding settings or maintaining separate codebases is a disaster waiting to happen.

Spring Boot’s Profiles feature allows you to define environment-specific configurations that seamlessly switch based on where the application runs.

In this guide, you’ll learn how to use Spring Boot Profiles like a seasoned engineer, covering:

  • Why Profiles are essential
  • How to configure properties for multiple environments
  • How to switch between them
  • Advanced usage with YAML, @Profile, and command-line arguments

Watch the Video Tutorial

Want a step-by-step walkthrough? Watch my YouTube video where I explain everything in detail!

Why Do You Need Spring Boot Profiles?

Imagine you have these environments:

EnvironmentDatabaseLogging LevelAPI URL
DevPostgreSQLDEBUGhttps://dev-api.example.com
StagingPostgreSQLINFOhttps://staging-api.example.com
ProductionPostgreSQLERRORhttps://api.example.com

Without Spring Boot Profiles, you’d have to manually change configurations before each deployment. That’s not just error-prone—it’s unacceptable in real-world applications.

Configuring Profiles with Property Files

The easiest way to use profiles is by defining environment-specific .properties or .yaml files.

1. Using .properties Files

Spring Boot loads properties from application.properties by default. But you can create environment-specific property files:

  • application-dev.properties
  • application-staging.properties
  • application-prod.properties

Each file contains environment-specific settings:

src/main/resources/application-dev.properties

spring.datasource.url=jdbc:postgresql://localhost:5432/mydb
spring.datasource.username=username
spring.datasource.password=password
logging.level.org.springframework=DEBUG
app.api.url=https://dev-api.example.com

src/main/resources/application-prod.properties

spring.datasource.url=jdbc:postgresql://prod-db:5432/mydb
spring.datasource.username=prod_user
spring.datasource.password=securePassword
logging.level.org.springframework=ERROR
app.api.url=https://api.example.com

Spring Boot will automatically pick the correct file based on the active profile.

How to Set the Active Profile

1. Using application.properties (Default Profile)

If no profile is specified, Spring Boot loads application.properties.

To explicitly set a default profile, add this in application.properties:

spring.profiles.active=dev

2. Using Command-Line Arguments

You can set the profile dynamically at runtime:

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

This method is commonly used in CI/CD pipelines and production deployments.

3. Using Environment Variables (Best for Containers/Kubernetes)

For Docker and Kubernetes deployments, you can use an environment variable:

export SPRING_PROFILES_ACTIVE=staging

Using YAML for Profile-Based Configuration

If you prefer YAML, you can either do the same thing as properties (have one file per env) or can define all environments on a single one:

application.yml

spring:
  profiles:
    active: dev  # Default profile

---
spring:
  config:
    activate:
      on-profile: dev
  datasource:
    url: jdbc:postgresql://localhost:5432/mydb
    username: username
    password: password
  logging:
    level:
      org.springframework: DEBUG
  app:
    api:
      url: <https://dev-api.example.com>

---
spring:
  config:
    activate:
      on-profile: prod
  datasource:
    url: jdbc:postgresql://prod-db:5432/mydb
    username: prod_user
    password: securePassword
  logging:
    level:
      org.springframework: ERROR
  app:
    api:
      url: <https://api.example.com>

This YAML setup ensures that Spring Boot automatically loads the correct configuration when switching profiles.

Using @Profile to Load Beans Based on the Active Profile

Spring Boot also lets you define beans that only load for specific profiles.

Example:

Define two different DataSource beans, one for dev and one for production.

@Configuration
public class DataSourceConfig {

    @Bean
    @Profile("dev")
    public DataSource h2DataSource() {
        System.out.println("Loading H2 DataSource for Dev");
        return new HikariDataSource(new HikariConfig("/h2-datasource.properties"));
    }

    @Bean
    @Profile("prod")
    public DataSource postgresDataSource() {
        System.out.println("Loading PostgreSQL DataSource for Prod");
        return new HikariDataSource(new HikariConfig("/postgres-datasource.properties"));
    }
}

When the app runs:

  • If dev is active, it loads the H2 database.
  • If prod is active, it loads PostgreSQL.

This approach eliminates unnecessary beans and improves performance.

Best Practices for Managing Spring Boot Profiles

  1. Never commit sensitive credentials in properties files.
    • Use environment variables or secrets management tools (e.g., AWS Secrets Manager, HashiCorp Vault).
  2. Always set a default profile (spring.profiles.active=dev).
    • Prevents unexpected behavior when running locally.
  3. Use @Profile to optimize performance.
    • Avoids loading unnecessary beans in production.
  4. Use command-line arguments for CI/CD pipelines.
    • Ensures the right profile is active during deployments.
  5. Document your profiles in README.md.
    • Make it easy for new developers to understand the environments.

Conclusion

Spring Boot Profiles are a powerful and flexible way to manage configurations across multiple environments.

By following the best practices outlined here, you can effortlessly switch environments and deploy confidently without modifying your code.

Leave a Reply

Your email address will not be published. Required fields are marked *