---
url: /operate/configuration.md
description: >-
  How a service's configuration takes effect: Spring Boot's sources and relaxed
  names, map keys, durations, what must match across nodes, development
  defaults, and the checks that catch a mistyped key.
---

# Configure a Service

A service is configured as any Spring Boot application is: `application.yaml`, profiles, environment variables and command-line arguments, under the prefix `wow`. Most keys have defaults that fit production. This page explains how the configuration takes effect and what the host checks. [Configuration Keys](../reference/configuration) lists every key, with its type and default.

## Where the values come from

The host reads Spring Boot's environment, so every source Spring Boot knows works, in its order of precedence: command-line arguments over environment variables over profile-specific files over `application.yaml`. Names bind relaxed: `wow.log.max-poll-interval`, `wow.log.maxPollInterval` and the environment variable `WOW_LOG_MAXPOLLINTERVAL` are one key.

Keep secrets out of the files. The eShop's configuration reads each one from an environment variable with a development default beside it, such as `${WOW_INTERNAL_TOKEN:…}`, and a deployment sets the variable from its secret store.

## Write the values

| Value | Written as |
| --- | --- |
| A duration | `500ms`, `30s`, `5m`, or ISO-8601 `PT30S` |
| A list | A YAML list, or a comma-separated string from an environment variable: `WOW_INTERNAL_TOKEN=a…,b…` |
| A key of a map that holds dots | In brackets: `wow.aggregates.[eshop-ordering.order].tenant`, `wow.subscriptions.[OrderSummaryProjection.onEvent].start` |

In YAML, quote a bracketed key so the brackets stay part of it:

```yaml
wow:
  subscriptions:
    "[ShipmentNotifier.onOrderShipped]":
      retry:
        max-attempts: 8
```

## Names are checked

The host refuses to start on a name that matches nothing it serves, rather than ignoring it: a subscription under `wow.subscriptions` that no handler is, an aggregate type under `wow.aggregates` the node does not serve, a context under `wow.contexts` that is on no class path, an id generator nothing provides.

## Keys are checked

Spring ignores a key no property binds, so a misspelled key would leave its default in place without a word. The host compares every `wow.*` key with the configuration metadata on the class path when it starts:

* An unknown key is logged as a warning that names it.
* An unknown key under `wow.cosec.`, `wow.http.services.`, `wow.calls.` or `wow.internal.` stops the start. Under `wow.http.services` and `wow.calls.contexts`, each entry's own keys are checked too: a mistyped `commands` would otherwise leave a service allowed to call every command.

Environment variables are not checked, because their names cannot be listed back. Check a deployment's variables against the reference when you set them.

## What must match across nodes

The nodes of one service form one cluster, so some settings must be the same on every node, and should change only as the reference describes:

* `wow.service`, the service's name, `spring.application.name` by default.
* `wow.log.partitions`: a power of two that divides 4,096 (64 by default), fixed once the log holds entries. Choose it before the first deployment.
* `wow.internal.token`: the cluster tokens. Rotate a token by adding the new one second, then moving it first on every node, then removing the old one.
* The stores and the placement of each aggregate type: `wow.backend`, `wow.stores`, `wow.log.store`, `wow.snapshot.*`, `wow.aggregates.*.log`.

## Development and production

A few defaults relax in a development profile, `dev`, `local`, `test` or `demo` (`wow.internal.dev-profiles`), or when the internal port binds the loopback interface alone:

| Without | In development | In production |
| --- | --- | --- |
| A `DataSource` or `MongoClient` | Runs in memory, with a warning | Refuses to start |
| A cluster token | The internal port runs without one | Refuses to start |

So a laptop needs no database and no secret, and a production node cannot start with either missing. `wow.ddl: validate` keeps a production node from creating tables ([PostgreSQL](./postgresql#manage-the-schema)).

## See what the node took

Spring Boot Actuator's `configprops` and `env` endpoints, when the application exposes them, show the values each key is bound to. Expose them on a management port only: they show the configuration of the node.
