Dynamic Environment Configuration in Spring Boot Using Profiles

Configure a local default, override the active profile at deployment, and use @Profile to select one service implementation in Spring Boot.

Spring Boot profiles select configuration and beans for an environment. This example uses @Profile to choose one greeting service for local or prod. It uses Spring Boot 3.5 profile behavior and assumes an existing Boot project with the classes in one component-scanned package.

Define the shared service

public interface GreetingService {
    void printMessage();
}

Set the active profile

Put spring.profiles.active=local in the base application.properties for this local example. Override it at deployment with --spring.profiles.active=prod. Do not put spring.profiles.active in application-local.properties or application-prod.properties. Profile-specific files are for settings used after a profile has been selected.

spring.profiles.active=local

Implement the local service

import org.springframework.context.annotation.Profile;
import org.springframework.stereotype.Service;

@Service
@Profile("local")
public class LocalGreetingService implements GreetingService {
    @Override
    public void printMessage() {
        System.out.println("Welcome to the Local Environment");
    }
}

Implement the production service

import org.springframework.context.annotation.Profile;
import org.springframework.stereotype.Service;

@Service
@Profile("prod")
public class ProdGreetingService implements GreetingService {
    @Override
    public void printMessage() {
        System.out.println("Welcome to the Production Environment");
    }
}

Run the selected service

import org.springframework.boot.CommandLineRunner;
import org.springframework.boot.SpringApplication;
import org.springframework.boot.autoconfigure.SpringBootApplication;
import org.springframework.context.annotation.Bean;

@SpringBootApplication
public class ProfileApplication {
    public static void main(String[] args) {
        SpringApplication.run(ProfileApplication.class, args);
    }

    @Bean
    CommandLineRunner greetingRunner(GreetingService greetingService) {
        return args -> greetingService.printMessage();
    }
}

Save each public type in its matching Java file. With the Boot build plugin configured, package the existing project and run its executable JAR using java -jar app.jar --spring.profiles.active=prod. The runner requests one GreetingService, so activating neither profile or both profiles requires an explicit selection policy instead of assuming a unique bean.

Verify profile selection

Check that the local default creates only the local service, then repeat with the command-line prod override. The isolated test accompanying this correction exercises both selections against Spring Boot 3.5.9. A mock of a service verifies delegation, but does not verify which profile selects that service.

The restriction on active-profile settings is documented in Spring Boot’s profiles reference. For the startup sequence around configuration loading, read SpringApplication.run().

Share
Prabhat Kashyap

Prabhat Kashyap

Senior Technical Architect at HCLTech · working with Leonteq Security AG

I have 10+ years of experience building distributed systems and fintech platforms. I write about practical, non-obvious engineering details that official documentation often skips.

Newsletter

Get new engineering deep dives

Scala, JVM, AI, and backend systems. I send practical articles when there is something worth reading.

Join the newsletter