Skip to content
Spring Boot core 2 min read

Configuration & Profiles

Spring Boot’s externalized configuration lets one build artifact run unchanged across environments. Settings live outside the code, in YAML, environment variables, or command-line arguments, and Spring binds them to typed objects.

application.yml

YAML is the idiomatic format for hierarchical configuration. Spring Boot reads application.yml from the classpath automatically.

server:
  port: 8080
app:
  name: Devcraftly Shop
  feature-flags:
    new-checkout: true
  retry:
    max-attempts: 3
    backoff-ms: 500

Reading single values with @Value

@Value injects an individual property using placeholder syntax, with an optional default after the colon.

@Service
public class GreetingService {

    @Value("${app.name}")
    private String appName;

    @Value("${app.timeout:30}")  // default 30 if missing
    private int timeoutSeconds;
}

Note: @Value is fine for one or two properties, but it offers no type safety for groups and scatters config keys across your codebase.

Typed binding with @ConfigurationProperties

For related settings, bind a whole tree to a typed class. This gives you validation, IDE completion, and a single source of truth.

@Configuration
@ConfigurationProperties(prefix = "app.retry")
@Validated
public class RetryProperties {

    @Min(1)
    private int maxAttempts;
    private long backoffMs;

    // getters and setters
}

Inject it like any other bean:

@Service
public class OrderClient {
    private final RetryProperties retry;

    public OrderClient(RetryProperties retry) {
        this.retry = retry;
    }
}

Tip: Prefer @ConfigurationProperties over multiple @Value annotations. It is type-safe, supports relaxed binding (max-attempts maps to maxAttempts), and validates at startup.

Spring Profiles

Profiles let you maintain environment-specific configuration. Create application-<profile>.yml files that override the base application.yml.

# application-dev.yml
spring:
  datasource:
    url: jdbc:h2:mem:devdb
logging:
  level:
    org.hibernate.SQL: DEBUG
# application-prod.yml
spring:
  datasource:
    url: jdbc:postgresql://db:5432/shop
logging:
  level:
    root: WARN

Activate a profile at runtime:

java -jar app.jar --spring.profiles.active=prod
# or via environment variable
export SPRING_PROFILES_ACTIVE=prod

You can also restrict beans to specific profiles:

@Bean
@Profile("dev")
public CommandLineRunner sampleData(ProductRepository repo) {
    return args -> repo.save(new Product("Demo", BigDecimal.TEN));
}

Externalized config and precedence

Spring Boot merges configuration from many sources in a defined order. Higher-priority sources override lower ones.

PrioritySource
HighestCommand-line arguments
SPRING_APPLICATION_JSON
OS environment variables
Profile-specific application-<profile>.yml
LowestBase application.yml

This precedence is what makes the same JAR portable: defaults ship in YAML, and each environment overrides only what differs.

Environment variables

Spring’s relaxed binding maps environment variables to properties: uppercase the key and replace dots with underscores. So app.name becomes APP_NAME.

export SERVER_PORT=9090
export SPRING_DATASOURCE_URL=jdbc:postgresql://db:5432/shop
java -jar app.jar

This convention is essential for containerized and cloud deployments, where secrets and connection strings arrive as environment variables rather than files.

Warning: Never commit secrets (passwords, API keys) to application.yml. Inject them through environment variables or a secrets manager, and keep only safe defaults in version control.

Best Practices

  • Use @ConfigurationProperties for grouped settings; reserve @Value for one-off values.
  • Keep one base application.yml plus thin profile-specific overrides, never duplicate full configs.
  • Externalize all environment-specific and sensitive values through environment variables.
  • Validate configuration at startup with @Validated to fail fast on misconfiguration.
  • Activate profiles explicitly per environment; avoid relying on a default profile in production.
  • Document required properties so operators know exactly what each environment must supply.
Last updated June 1, 2026
Was this helpful?