By WebNest Studio Engineering Team
Spring Framework Tutorial
Spring Profiles
Real applications behave differently depending on where they run — a development machine, a test environment, or production. Spring Profiles let you tag beans and configuration so that only the ones matching the currently active profile are registered in the container, making it possible to swap entire sets of beans (like a mock email service in dev versus a real SMTP client in production) without touching code.
A profile is nothing more than a named label. You mark beans or configuration classes with @Profile("name"), and then activate one or more profiles at startup through a property, environment variable, or command-line argument. Beans with no @Profile annotation are always active regardless of which profiles are set.
Declaring Profile-Specific Beans
@Profile can be placed on an individual @Bean method, on an entire @Configuration class, or on a @Component/@Service class. When the annotated element's profile does not match any currently active profile, Spring simply skips registering that bean — it does not exist in the container at all, so attempting to autowire it elsewhere without a matching alternative will fail.
@Profile("dev")— bean is only registered when the "dev" profile is active.@Profile("!prod")— bean is registered whenever "prod" is NOT active (profile negation).@Profile({"dev", "test"})— bean is registered if either "dev" or "test" is active.
Activating Profiles
Profiles are activated via the spring.profiles.active property, which can be set as a JVM argument (-Dspring.profiles.active=dev), an environment variable, a property in application.properties/yml (in Spring Boot), or programmatically on the context's Environment before refresh. Multiple profiles can be active simultaneously, comma-separated, and all beans matching any of the active profiles are registered together.
Typical Use Cases
Common patterns include swapping a real payment gateway or email client for a stub/mock implementation in "dev" or "test" profiles, pointing at different database connection settings per environment, or enabling verbose debug logging beans only outside "prod". Profiles keep environment-specific wiring in the codebase in a controlled, explicit way rather than relying on scattered if-checks.
Example
Two mutually exclusive beans selected by active profile
import org.springframework.context.ApplicationContext;
import org.springframework.context.annotation.AnnotationConfigApplicationContext;
import org.springframework.context.annotation.Bean;
import org.springframework.context.annotation.Configuration;
import org.springframework.context.annotation.Profile;
interface EmailSender {
void send(String message);
}
@Configuration
class EmailConfig {
@Bean
@Profile("dev")
public EmailSender devEmailSender() {
return message -> System.out.println("[DEV] Would send email: " + message);
}
@Bean
@Profile("prod")
public EmailSender prodEmailSender() {
return message -> System.out.println("[PROD] Sending real email: " + message);
}
}
public class ProfileDemo {
public static void main(String[] args) {
AnnotationConfigApplicationContext context = new AnnotationConfigApplicationContext();
context.getEnvironment().setActiveProfiles("dev");
context.register(EmailConfig.class);
context.refresh();
EmailSender sender = context.getBean(EmailSender.class);
sender.send("Order confirmation");
}
}
[DEV] Would send email: Order confirmation
Common Mistakes
- Forgetting to activate any profile, then being confused when a @Profile("dev")-only bean is missing from the context — no profile active means no profile-restricted beans are registered.
- Defining two beans of the same type under different profiles but forgetting one of them for the "default" (no-profile) case, causing startup failures in environments where no profile is set.
- Activating conflicting profiles simultaneously (e.g. "dev" and "prod" together) and getting duplicate or ambiguous bean definitions of the same type.
- Using @Profile on individual @Bean methods inconsistently with the surrounding @Configuration class's own @Profile, leading to confusing partial activation.
Exercise
A teammate is about to make this mistake: Forgetting to activate any profile, then being confused when a @Profile("dev")-only bean is missing from the context — no profile active means no profile-restricted beans are registered. Use Declaring Profile-Specific Beans to review the decision. Write a corrected implementation or design sketch that follows @Profile("name") restricts a bean or configuration class to only be active when that profile is active., then name one edge case you would check.
Show hints
- Start with Declaring Profile-Specific Beans and compare your approach with Two mutually exclusive beans selected by active profile. Identify the decision or behavior the lesson recommends.
- Walk through your scenario step by step. Confirm that it follows @Profile("name") restricts a bean or configuration class to only be active when that profile is active. and that it would catch the failure described by Forgetting to activate any profile, then being confused when a @Profile("dev")-only bean is missing from the context — no profile active means no profile-restricted beans are registered..
Quick quiz
1. Which choice best describes the recommended approach in Spring Profiles?
- A. Forgetting to activate any profile, then being confused when a @Profile("dev")-only bean is missing from the context — no profile active means no profile-restricted beans are registered.
- B. Defining two beans of the same type under different profiles but forgetting one of them for the "default" (no-profile) case, causing startup failures in environments where no profile is set.
- C. @Profile("name") restricts a bean or configuration class to only be active when that profile is active.
Show answer
C. This is the recommended approach: @Profile("name") restricts a bean or configuration class to only be active when that profile is active. Avoid: Forgetting to activate any profile, then being confused when a @Profile("dev")-only bean is missing from the context — no profile active means no profile-restricted beans are registered.
Interview questions
Why does this principle matter in Spring Profiles: @Profile("name") restricts a bean or configuration class to only be active when that profile is active.
Show answer
@Profile("name") restricts a bean or configuration class to only be active when that profile is active. Apply this in Declaring Profile-Specific Beans; the example Two mutually exclusive beans selected by active profile shows one way to do it. Avoid Forgetting to activate any profile, then being confused when a @Profile("dev")-only bean is missing from the context — no profile active means no profile-restricted beans are registered. and explain how your implementation or design prevents that failure.
Key Points to Remember
- @Profile("name") restricts a bean or configuration class to only be active when that profile is active.
- Profiles are activated via spring.profiles.active (JVM arg, env var, or Boot property), and multiple can be active at once.
- Beans without any @Profile annotation are always registered, regardless of active profiles.
- Profiles are commonly used to swap environment-specific implementations like mail senders or data sources.
Practice in the playground
Write and run your own code for this topic, or start from the exercise or an example. Runs plain Java 17. Frameworks such as Spring, and databases, are not available here. Your code for each topic is kept in this browser.
Run the examples
Change an input, predict the result, then compare it with the output. Explain why the result changes.
These examples need a JDK project with their libraries on your computer, so they can be copied but not run here. Codelab runs Python, FastAPI backends with SQLite, plain Java 17 and HTML/CSS/JavaScript.
Written by
WebNest Studio Engineering Team
Practical lessons from developers working with Java, Python, React, databases and production systems.
Led by Vansh Duggal, Founder, WebNest Studio · Full-stack & software engineering