Spring Boot
Profiles
Spring Boot 2.4.0
Java
Application Development

Including profiles in spring boot 2.4.0 version

Master System Design with Codemia

Enhance your system design skills with over 120 practice problems, detailed solutions, and hands-on exercises.

Introduction

Spring Boot 2.4.0 overhauled how external configuration and profiles work. The previous spring.profiles and spring.profiles.include properties were replaced with a new activation model built around spring.config.activate.on-profile. If you are upgrading from an earlier Spring Boot version, understanding these changes is essential to avoid broken configurations. This article covers the new profile activation syntax, profile groups, multi-document YAML files, and the migration steps you need to follow.

What Changed and Why

Before 2.4.0, you could write this in an application.yml to restrict a document section to a specific profile:

yaml
1# OLD (pre-2.4.0) -- no longer works by default
2spring:
3  profiles: production
4server:
5  port: 8443

The problem was that spring.profiles served double duty: it both activated profiles and filtered which document sections loaded. This created confusing interactions when combining spring.profiles with spring.profiles.include. Spring Boot 2.4.0 separated these concerns by introducing dedicated properties.

The New Activation Model

spring.config.activate.on-profile

To conditionally load a section of configuration, use spring.config.activate.on-profile instead of the old spring.profiles:

yaml
1# NEW (2.4.0+)
2spring:
3  config:
4    activate:
5      on-profile: production
6server:
7  port: 8443

This property accepts profile expressions, including ! (not), & (and), and | (or):

yaml
1spring:
2  config:
3    activate:
4      on-profile: "production & !debug"
5server:
6  port: 8443
7  ssl:
8    enabled: true

Multi-Document YAML with ---

Spring Boot 2.4.0 brought multi-document support to application.yml (using --- separators) and even to .properties files (using #---). Each document section can have its own activation condition:

yaml
1# Default settings (no profile filter)
2server:
3  port: 8080
4logging:
5  level:
6    root: INFO
7
8---
9# Activated only when "dev" profile is active
10spring:
11  config:
12    activate:
13      on-profile: dev
14logging:
15  level:
16    root: DEBUG
17    com.example: TRACE
18
19---
20# Activated only when "production" profile is active
21spring:
22  config:
23    activate:
24      on-profile: production
25server:
26  port: 8443
27logging:
28  level:
29    root: WARN

The equivalent in application.properties uses #--- as the document separator:

properties
1# Default
2server.port=8080
3
4#---
5# Dev profile
6spring.config.activate.on-profile=dev
7logging.level.root=DEBUG
8
9#---
10# Production profile
11spring.config.activate.on-profile=production
12server.port=8443

Profile Groups

Spring Boot 2.4.0 introduced profile groups, which let you activate multiple profiles under a single group name. This is useful when an environment requires several profiles to be active simultaneously:

yaml
1spring:
2  profiles:
3    group:
4      production:
5        - proddb
6        - prodmq
7        - prodmetrics
8      staging:
9        - stagingdb
10        - stagingmq

Now activating the production profile (via --spring.profiles.active=production) automatically activates proddb, prodmq, and prodmetrics as well. This replaces many uses of the old spring.profiles.include.

Migration Steps

If you are upgrading from Spring Boot 2.3 or earlier, follow these steps:

  1. Replace spring.profiles with spring.config.activate.on-profile. Search your YAML and properties files for spring.profiles: (used as a document filter) and rewrite it.
  2. Replace spring.profiles.include with profile groups. If you were using spring.profiles.include inside a profile-specific document, move that logic into spring.profiles.group in the default (non-profile-filtered) document.
  3. Enable the legacy mode if needed. If you cannot migrate immediately, set spring.config.use-legacy-processing=true in your main application.properties to restore pre-2.4 behavior. This is a temporary bridge -- plan to remove it.
  4. Test multi-document ordering. In the new model, later documents override earlier ones. Verify that your property precedence is correct by running with --debug and inspecting the PropertySource log output.
yaml
1# Temporary legacy bridge (remove after full migration)
2spring:
3  config:
4    use-legacy-processing: true

Common Pitfalls

  • Using spring.profiles in a profile-activated document. In 2.4.0+, placing spring.profiles inside a ----separated section throws an error unless legacy processing is enabled. Always use spring.config.activate.on-profile instead.
  • Placing spring.config.activate.on-profile in the first document. The first document in a multi-document file is the default and cannot have an activation condition. Spring Boot will reject this with a configuration error. Put profile-specific sections in subsequent documents only.
  • Forgetting the #--- separator in properties files. Multi-document support in .properties files requires exactly #--- on its own line. Using # --- (with a space) or --- (without the #) does not work and silently treats the entire file as a single document.
  • Mixing spring.profiles.include with the new model. Using spring.profiles.include inside a profile-activated document is not allowed in the new processing model. Move inclusion logic to spring.profiles.group in the default document section.
  • Not testing profile activation order. The new model processes documents top to bottom, with later values overriding earlier ones. If you reorder your --- sections or add new ones, previously working property values can be silently overwritten. Always verify with the --debug flag.

Summary

  • Spring Boot 2.4.0 replaced spring.profiles (document filter) with spring.config.activate.on-profile, which supports profile expressions like production & !debug.
  • Multi-document YAML (---) and properties (#---) files let you keep all profile-specific configuration in a single file.
  • Profile groups (spring.profiles.group) replace most uses of spring.profiles.include and let you activate multiple profiles under one name.
  • Set spring.config.use-legacy-processing=true as a temporary bridge during migration, but plan to remove it.
  • Always test property precedence after migration because document ordering determines which values win.

Course illustration
Course illustration