Learn how to use Spring Boot profiles to manage environment-specific services and configurations, ensuring flexibility and reducing deployment errors.
Learn how to use Spring Boot profiles to manage environment-specific services and configurations, ensuring flexibility and reducing deployment errors.
In a typical software development lifecycle, applications need to adapt to various environments like development, testing, and production. Each environment has its own specific configurations, such as database connections, messaging services, or even simple greeting messages. Instead of hardcoding these settings, Spring Boot offers a powerful feature called Profiles, which allows you to define and load environment-specific configurations dynamically. This blog post will show you how to create a simple Spring Boot application that prints different messages depending on whether it’s running in a local or production environment.
We will create two services, each printing a different message. The service used will depend on whether the application is running in a local environment or in production. This will demonstrate the flexibility of Spring profiles for environment-specific behavior.
First, we’ll create an interface that both the local and production implementations will adhere to:
public interface GreetingService {
void printMessage();
}JavaWe’ll use separate configuration files for local and production environments, with a default application.properties file to specify the active profile.
application.properties:
# Default profile
spring.profiles.active=localapplication-local.properties:
spring.profiles.active=localapplication-prod.properties:
spring.profiles.active=prodNow, implement the GreetingService for the local environment:
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");
}
}JavaSimilarly, implement the GreetingService for the production environment:
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");
}
}JavaNext, create a service that uses the GreetingService to print the appropriate message based on the active profile:
import org.springframework.stereotype.Service;
@Service
public class MessageService {
private final GreetingService greetingService;
public MessageService(GreetingService greetingService) {
this.greetingService = greetingService;
}
public void printEnvironmentMessage() {
greetingService.printMessage();
}
}Javaspring.profiles.active=local in application.properties.application-prod.properties or through command-line arguments when starting the application:spring.profiles.active=prodPlaintextWhen writing unit tests, you can mock the GreetingService to test how your MessageService behaves without relying on the actual environment:
import org.junit.jupiter.api.Test;
import org.mockito.Mockito;
import static org.mockito.Mockito.*;
class MessageServiceTest {
@Test
void testPrintEnvironmentMessage() {
// Arrange
GreetingService mockGreetingService = mock(GreetingService.class);
MessageService messageService = new MessageService(mockGreetingService);
// Act
messageService.printEnvironmentMessage();
// Assert
verify(mockGreetingService).printMessage();
}
}JavaUsing Spring profiles and environment-specific configuration files, you can easily switch between different services or settings depending on the environment your application is running in. This approach ensures that your application remains flexible and adaptable, minimizing the need for code changes when moving between development and production environments.

10+ years building distributed systems and fintech platforms. I write about the things I actually debug at work — the messy, non-obvious parts that don't make it into official docs.
Engineering deep dives on Scala, Java, Rust, and AI Systems. Written by a senior engineer who builds real fintech systems.
TOPICS
© 2026 prabhat.dev