spring.profiles.active

Lists the profiles that are active, which decides which profile-specific files and @Profile beans load; set it per deployment, not in the jar.

Signature
spring.profiles.active=prod
  • Added in Spring Boot Spring Boot 4.1 (verified present)

Parameters

ParameterTypeDescription
$valueoptionalList<String>Profile names in order. Later profiles override earlier ones where their properties overlap.
$spring.profiles.defaultoptionalString= defaultProfile used only when no profile is active.
$spring.profiles.includeoptionalList<String>Profiles added unconditionally on top of the active ones.
$spring.profiles.group.<name>optionalList<String>Expands one profile name into several, for example prod into prod, postgres and json-logs.

Return value

n/aThe comma-separated list of active profiles. Active profiles select application-{profile}.properties files, documents with spring.config.activate.on-profile, and beans annotated with @Profile.

Errors

Setting it inside a profile-specific file or document fails startup with an InvalidConfigDataPropertyException.

A profile is a named slice of configuration. spring.profiles.active says which slices apply to this run: Boot then loads application-{profile}.properties for each one, includes YAML documents marked with spring.config.activate.on-profile, and creates beans annotated with @Profile for those names.

Set it outside the jar

The same artefact should run everywhere, so the active profile belongs to the deployment. The usual ways, from lowest to highest precedence among the common sources:

SPRING_PROFILES_ACTIVE=prod java -jar app.jar
java -jar app.jar --spring.profiles.active=prod

Putting spring.profiles.active=dev in the main application.properties is a classic way to ship a development profile to production: any environment that forgets to override it runs with local settings. If you want a fallback for laptops, use spring.profiles.default=dev, which applies only when nothing else is active.

Rules people trip over

  • Values from different sources do not merge. SPRING_PROFILES_ACTIVE=prod replaces the list from the properties file rather than adding to it. Use spring.profiles.include or a group for profiles that must always be on.
  • The property may not appear in a profile-specific file or document, because the profile list has to be settled before those files are read. Startup fails if you try.
  • Order matters. With prod,eu the eu file is applied after prod and wins where both set a key.
  • A typo is silent. --spring.profiles.active=prd starts happily with no prd file. Boot logs the active profiles at startup; check that line after every deployment change.

Groups keep the list short

spring.profiles.group.prod=postgres,json-logs,metrics

Activating prod now activates the whole set. Operations set one name; the composition lives in version control.

In tests, prefer @ActiveProfiles on the test class over environment variables, so the test documents the configuration it relies on.

Example

Example · properties
# application.properties (inside the jar)

# Used only when the deployment activates nothing, e.g. on a laptop.
spring.profiles.default=dev

# One name for operations to set; the details stay in version control.
spring.profiles.group.prod=postgres,json-logs
spring.profiles.group.dev=h2,pretty-logs

When to use it

  • Running one container image in staging and production with different databases and log formats
  • Swapping a real payment provider for a fake one in development and tests, with the real one as the default
  • Giving developers a working local setup without any flags through spring.profiles.default

Frequently asked questions

How do I set the active profile in Spring Boot?

Use the SPRING_PROFILES_ACTIVE environment variable or the --spring.profiles.active argument, with comma-separated names. In tests use @ActiveProfiles. Avoid setting it in the application.properties inside the jar.

Why is my profile from application.properties ignored?

A higher-precedence source, such as SPRING_PROFILES_ACTIVE in the environment, also sets the property and replaces the whole list. Values from different sources are not combined; use spring.profiles.include or groups for profiles that must always be on.

What is the difference between spring.profiles.active and spring.profiles.default?

active is the list for this run. default (normally the profile called default) applies only when no profile is active, which makes it a safe place for a local development fallback.

More examples

Activating profiles per environment

Every form sets the same property. On a container platform the environment variable is the natural fit, because the image stays identical across environments and only the deployment manifest changes.

Example · bash
# Local run with Maven
./mvnw spring-boot:run -Dspring-boot.run.profiles=dev

# Packaged jar, environment variable
SPRING_PROFILES_ACTIVE=prod java -jar target/orders.jar

# Packaged jar, argument (wins over the variable)
java -jar target/orders.jar --spring.profiles.active=prod,eu

# Container
docker run -e SPRING_PROFILES_ACTIVE=prod -p 8080:8080 orders:1.4.0

Beans that exist only in some profiles

Exactly one PaymentGateway exists in any run: the fake one in dev or test, the real one everywhere else. Making the real gateway the default is deliberate: a production deployment that forgets its profile still charges customers for real, instead of silently accepting orders through a fake.

Example · java
import java.time.Clock;
import java.time.Instant;
import java.time.ZoneOffset;
import org.springframework.context.annotation.Bean;
import org.springframework.context.annotation.Configuration;
import org.springframework.context.annotation.Profile;

interface PaymentGateway {
    String charge(String customerId, long amountInPence);
}

class StripeLikeGateway implements PaymentGateway {
    public String charge(String customerId, long amountInPence) {
        throw new UnsupportedOperationException("calls the real provider");
    }
}

class FakeGateway implements PaymentGateway {
    public String charge(String customerId, long amountInPence) {
        return "fake-" + customerId + "-" + amountInPence;
    }
}

@Configuration
public class PaymentConfig {

    @Bean
    @Profile("!dev & !test")
    PaymentGateway realGateway() {
        return new StripeLikeGateway();
    }

    @Bean
    @Profile({"dev", "test"})
    PaymentGateway fakeGateway() {
        return new FakeGateway();
    }

    @Bean
    @Profile("demo")
    Clock frozenClock() {
        return Clock.fixed(Instant.parse("2026-01-01T09:00:00Z"), ZoneOffset.UTC);
    }
}

Choosing the profile in a test

@ActiveProfiles makes the test independent of whatever SPRING_PROFILES_ACTIVE the CI agent happens to have. Environment.matchesProfiles accepts the same expressions as @Profile, which is handy in assertions and conditional code.

Example · java
import static org.assertj.core.api.Assertions.assertThat;

import org.junit.jupiter.api.Test;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.boot.test.context.SpringBootTest;
import org.springframework.core.env.Environment;
import org.springframework.test.context.ActiveProfiles;

@SpringBootTest
@ActiveProfiles({"test", "h2"})
class ProfileSelectionTest {

    @Autowired
    Environment environment;

    @Test
    void runsWithTheDeclaredProfiles() {
        assertThat(environment.getActiveProfiles()).containsExactly("test", "h2");
        assertThat(environment.matchesProfiles("!prod")).isTrue();
    }
}

Discussion

  • Be the first to comment on this lesson.