
# Profiles

A profile is a name for a situation the application runs in, such as `dev`, `test`, `prod` or `eu`; activating it reads its config files and registers its beans.

## Why

Environments often differ by more than one or two values: another database, a fake payment service in development, other URLs per region. Profiles keep the shared setup in one place and put only the differences in profile files and profile beans. There is no `if` in `main`.

## Activating profiles

| Key | Meaning |
|---|---|
| `spring.profiles.active` | The active profiles, a comma list or a YAML list. The first source that has the key wins, so the command line beats a file. |
| `spring.profiles.include` | Profiles added to the active ones, from every source. |
| `spring.profiles.default` | The profiles used while none is active. `default` when not set. |
| `spring.profiles.group.<name>` | Activating `<name>` activates these too. Groups can contain groups. |
| `spring.profiles.validate` | `true` (the default) checks the names: letters, digits and `-_.+@`, starting and ending with a letter or digit. |

Profiles are usually chosen at launch:

```bash
dart run bin/main.dart --spring.profiles.active=prod
SPRING_PROFILES_ACTIVE=prod dart run bin/main.dart
flutter run --dart-define=SPRING_PROFILES_ACTIVE=prod
```

In code: `SpringApplication(additionalProfiles: [...])`, `run(args, additionalProfiles: [...])`, or `environment.addActiveProfile(...)` in an `EnvironmentPostProcessor`.

In Flutter apps, the platform and the build are profiles too, with no setup:

- `android`, `ios`, `web`, `macos`, `windows` or `linux`;
- `mobile` (Android, iOS) or `desktop` (macOS, Windows, Linux);
- `release`, `profile` or `debug`.

## Profile files

For each active profile, `application-<profile>.properties`, `.yml` or `.yaml` is read after the plain file, so its values win. The last active profile wins over the earlier ones.

```
lib/resources/
  application.yml          # always read
  application-dev.yml      # with dev
  application-prod.yml     # with prod
```

The profiles are decided before the profile files are read. So a profile file may not set `spring.profiles.active`, `.include` or `.default`; the start fails if it does. Its `spring.profiles.group.*` is ignored.

## Documents for some profiles

One file can hold several documents: YAML separates them with `---`, `.properties` with a line `#---`. `spring.config.activate.on-profile` limits a document to a profile expression. A later document overrides an earlier one.

```yaml
# lib/resources/application.yml
spring:
  profiles:
    active: dev
    group:
      prod: [eu, monitoring]
shop:
  url: http://localhost:8080
---
spring:
  config:
    activate:
      on-profile: "prod & !us"
shop:
  url: https://eu.neon.books
```

```properties
# lib/resources/application.properties: the same
spring.profiles.active=dev
spring.profiles.group.prod=eu,monitoring
shop.url=http://localhost:8080
#---
spring.config.activate.on-profile=prod & !us
shop.url=https://eu.neon.books
```

`spring.config.activate.on-cloud-platform` limits a document to a cloud platform instead: `kubernetes`, `heroku`, `cloud-foundry`, `azure-app-service`, `amazon-ecs`, `nomad`, `sap` or `none`.

## Profile expressions

The same expressions work in `on-profile`, `@Profile` and `Environment.matchesProfiles`.

| Expression | Matches when |
|---|---|
| `prod` | `prod` is active |
| `!prod` | `prod` is not active |
| `prod & eu` | both are active |
| `dev \| test` | either is active |
| `prod & (eu \| us)` | combinations, with parentheses |

`&` and `|` cannot be mixed without parentheses. A list (`@Profile(['dev', 'test'])`, or a comma list in `on-profile`) matches when any entry matches. While no profile is active, the default profiles count: `@Profile(['default'])` and `application-default.yml` apply to a run without profiles.

## Beans for some profiles

```dart
import 'package:spring_core_dart/spring_core_dart.dart';

abstract interface class Payments {
  Future<void> charge(int cents);
}

@Service()
@Profile(['prod'])
class StripePayments implements Payments {
  @override
  Future<void> charge(int cents) async {
    // call the payment provider
  }
}

@Service()
@Profile(['!prod'])
class FakePayments implements Payments {
  @override
  Future<void> charge(int cents) async {}
}

@Service()
class Diagnostics {
  Diagnostics(this.env);
  final Environment env;

  bool get verbose => env.matchesProfiles(['dev & !test']);
}
```

On a configuration class, `@Profile` applies to all its `@Bean` methods and to its `@PropertySource` files. See [@Profile](../beans/profile.md).

## In Spring (Java)

```java
@Service
@Profile("prod")
class StripePayments implements Payments { ... }
```

The keys, files and expressions are Spring Boot's. Differences that matter:

- `@Profile` takes a list: `@Profile(['dev', 'test'])`.
- Flutter apps get the platform and build profiles (`ios`, `web`, `release`...) by themselves.
- A document limited to a profile in `application.yml` may not set the `spring.profiles.*` activation keys; the start fails when the document applies.

## See also

- [@Profile](../beans/profile.md)
- [@Conditional](../beans/conditional.md)
- [Environment](environment.md)
- [Property sources](property-source.md)
- [Configuration](index.md)
