# Spring Boot profiles, config import and config trees Companion project for [**Spring Boot Profiles Done Right**](https://ankurm.com/) on ankurm.com. The question the project answers: you set a value in `application-prod.yaml`, deployed with `prod` active, and the old value is still in effect. Why? ## Versions | | | |---|---| | Spring Boot | 4.1.1 | | Spring Framework | 7.0.9 | | JDK | Eclipse Temurin 25.0.4.1 (LTS) | ## Quickstart ```bash export JAVA_HOME=/path/to/jdk-25 mvn -DskipTests package ./scripts/run-all.sh # regenerate every transcript in docs/output/ mvn test # 6 contract tests ``` ## Profiles | Profile | What it demonstrates | |---|---| | `prod` | a profile group expanding to `prod`, `prod-db`, `prod-metrics` | | `import` | `spring.config.import`, and the imported file winning | | `multidoc` | one file, three documents, activated by condition | | `badactivation` | `spring.profiles.active` set from a profile-specific document — refused | | `staging` | the conditional document inside `application-multidoc.yaml` | ## Endpoints | Endpoint | Purpose | |---|---| | `GET /precedence?name=` | every source holding a property, ranked, with file and line | | `GET /sources` | the live property-source stack in precedence order | Diagnostics. Delete before shipping, or use Actuator's `/actuator/env`, which sanitises. ## Documentation 1. [The precedence list](docs/01-the-precedence-list.md) 2. [Profiles: files, documents and groups](docs/02-profiles.md) 3. [Seeing precedence instead of reasoning about it](docs/03-seeing-precedence.md) 4. [Why your profile-specific file lost](docs/04-why-your-profile-file-lost.md) 5. [`spring.config.import`](docs/05-config-import.md) 6. [Config trees and Kubernetes ConfigMaps](docs/06-config-trees-and-configmaps.md) ## Captured output | File | Produced by | |---|---| | [`00-versions.txt`](docs/output/00-versions.txt) | `scripts/demo-versions.sh` | | [`01-precedence.txt`](docs/output/01-precedence.txt) | `scripts/demo-precedence.sh` | | [`02-profile-file-loses.txt`](docs/output/02-profile-file-loses.txt) | `scripts/demo-profile-file-loses.sh` | | [`03-config-tree.txt`](docs/output/03-config-tree.txt) | `scripts/demo-config-tree.sh` | | [`04-import-and-multidoc.txt`](docs/output/04-import-and-multidoc.txt) | `scripts/demo-import-and-multidoc.sh` | ## The short answer Config data — every file you write, profile-specific ones included — is item 3 in Spring Boot's documented precedence list. OS environment variables are item 5. Later items win. A profile-specific file beats other files and loses to the weakest environment variable on the host. ## The one that surprises people `spring.config.import` does not behave like `#include`. The **imported** file is processed after the file that declared the import, so it **wins**. Import a shared baseline expecting to override it and every key it sets will quietly beat yours.