Docs
Docs / Guides / Configuration

Configuration Guide

This guide explains how the service loads its configuration, which sources take precedence, and how to validate your settings before deploying. For the complete list of individual keys, see the config keys reference.

Configuration sources

At startup the service reads settings from three places:

All three are optional. Any key you do not set falls back to its built-in default.

Precedence rules

When the same key is set in more than one place, the last source in this list wins:

  1. Built-in defaults
  2. Configuration file
  3. Environment variables
  4. Command-line flags
A flag such as --port 9000 overrides APP_PORT=8080, which in turn overrides port: 3000 in the file.

The configuration file

A minimal file looks like this:

server:
  host: 0.0.0.0
  port: 8080
  read_timeout: 15s
  write_timeout: 30s

database:
  url: postgres://app@db.internal:5432/app
  max_connections: 20
  idle_timeout: 5m

logging:
  level: info
  format: json
  output: stdout

Durations accept suffixes ms, s, m, and h. Sizes accept KB, MB, and GB.

To load a file from a different location, use the --config flag:

app serve --config /etc/app/production.yaml

Environment variables

Nested keys map to environment variables by joining path segments with underscores and adding the APP_ prefix. Keys are upper-cased.

File keyEnvironment variable
server.portAPP_SERVER_PORT
database.urlAPP_DATABASE_URL
logging.levelAPP_LOGGING_LEVEL

Handling secrets

Do not commit passwords, tokens, or private keys to the configuration file. Instead, reference them from the environment or from a secrets file:

database:
  url: ${file:/run/secrets/db_url}

api:
  token: ${env:APP_API_TOKEN}
Values read through ${file:...} have trailing newlines stripped. Values from the environment are used exactly as set.

Validating configuration

Check a configuration without starting the server:

app config validate --config /etc/app/production.yaml

The command exits with status 0 when the configuration is valid. Otherwise it prints each problem with its key path and exits with status 2. Run it in your CI pipeline before each deploy.

To print the effective configuration after all sources are merged, with secrets redacted:

app config print --redact

Troubleshooting

The server ignores my change

Check whether an environment variable or flag is overriding the file. Run app config print to see the value that is actually in use.

“unknown key” errors

Keys are case-sensitive and must match the reference exactly. Unknown keys are rejected by default so that typos fail loudly. To allow them temporarily, set strict: false at the top level of the file.

Duration parse errors

A bare number such as 30 is not a valid duration. Add a unit, for example 30s.