Skip to content

Environment variables

How the broker reads configuration, which variables an operator actually touches, and every variable with the default the code applies.

Updated View as Markdown

The broker has no configuration file and no command-line flags. Every knob is an environment variable, read once by config::load() during boot, before the HTTP listener binds. There is no reload: changing a variable means restarting the process. The one argument the binary accepts is the subcommand migrate, which exists only to report that offline migration was retired and exit non-zero.

One boolean parser

Every boolean in the broker goes through the same parser, so =on, =1 and =true mean the same thing everywhere. The accepted spellings are true/false, 1/0, yes/no, on/off, case-insensitive, surrounding whitespace trimmed.

Three outcomes, and only three:

  • Recognised value: used.
  • Unset, or present but empty or whitespace-only: the documented default. JWT_ENABLED= in a Compose file means “leave it alone”, not false.
  • Anything else: a fatal boot error. The process logs FATAL: JWT_ENABLED="maybe" is not a boolean (expected true/false, 1/0, yes/no, on/off) and exits 1.

That last rule exists because the alternative failed in both directions: a strict parser with a silent fallback turned JWT_ENABLED=1 into a broker running with authentication off and nothing in the log. Booleans read outside config.rs (QUEEN_LOG_JSON, QUEEN_APPLY_SCHEMA, QUEEN_V2_BUNDLE_LOG) are validated eagerly at the same moment, so every boolean mistake in a deployment surfaces on the same boot with the same message.

Several numeric knobs are also clamped after parsing. Interval and size knobs are floored at 1, and STATS_INTERVAL_MS and METRICS_FLUSH_MS are floored at 1000 ms: a value below the floor is raised without comment.

The effective configuration is printed at boot

After the JWT configuration is validated, the broker emits one boot block per subsystem (config: server, postgres, auth, sync, engine, flow, jobs, file_buffer, security, logging) carrying the values it actually resolved. A misspelled variable, a defaulted knob, or a value that came from a legacy alias is visible there instead of having to be inferred from behaviour. Read that block first when a setting appears not to have taken effect.

Secrets are masked, never printed: JWT_SECRET, PG_PASSWORD, QUEEN_ENCRYPTION_KEY and QUEEN_SYNC_SECRET render as <unset> or <set:32 chars>. That is enough to tell “I forgot to mount the secret” from “I mounted the wrong one” without putting key material into a log shipper.

What kills the boot

The broker prefers to die at startup over serving in a state you did not ask for. All four of these exit 1:

  • an unparseable boolean, as above;
  • JWT_ENABLED=true with no usable key material for the configured algorithm, or an algorithm outside HS256, HS384, HS512, RS256, RS384, RS512, EdDSA, auto;
  • a schema apply failure (unless QUEEN_APPLY_SCHEMA=0);
  • failure to bind 0.0.0.0:$PORT.

One important omission from that list: a malformed QUEEN_ENCRYPTION_KEY (not 64 hex characters, or not hex) logs a single warning and disables encryption. Queues flagged encryptionEnabled then store plaintext and the pushes succeed. Grep the boot config: security block for encryption_key=<set:64 chars> before trusting at-rest encryption.

Which variables actually matter

Most of the table below is measured engine tuning that should be left alone. In practice a deployment sets variables from these groups only.

Purpose Variables
Reach PostgreSQL PG_HOST, PG_PORT, PG_USER, PG_PASSWORD, PG_DATABASE
Size the connection pool and bound statements DB_POOL_SIZE, QUEEN_STMT_TIMEOUT_MS
Encrypt broker-to-PostgreSQL traffic PG_USE_SSL, PG_SSL_REJECT_UNAUTHORIZED
Serve on a different port PORT
Turn on authentication JWT_ENABLED, JWT_ALGORITHM, then JWT_SECRET or JWT_PUBLIC_KEY or JWT_JWKS_URL
Run more than one broker QUEEN_MESH_PEERS, QUEEN_MESH_PORT, QUEEN_SYNC_SECRET
Survive a database outage FILE_BUFFER_DIR (must be writable and persistent)
Change the maintenance cadence RETENTION_INTERVAL
Accept larger request bodies QUEEN_MAX_BODY_BYTES
Encrypt payloads at rest QUEEN_ENCRYPTION_KEY
Shape the logs LOG_LEVEL, QUEEN_LOG_JSON, QUEEN_LOG_RATES_MS
Let a privileged role own the DDL QUEEN_APPLY_SCHEMA
Scope queues by tenant behind a proxy QUEEN_TENANCY_HEADER. See Self-hosting

Two conventions in that list are worth stating explicitly.

LOG_LEVEL accepts the full EnvFilter syntax, not just a bare level: info,queen::pop=debug works. RUST_LOG takes precedence over it, and an unparseable filter falls back to info.

PG_DATABASE resolves through a non-empty chain (PG_DATABASE, then the legacy PG_DB, then postgres), so an explicitly empty value falls through. Every other string variable keeps a present-but-empty value verbatim, which is how JWT_SKIP_PATHS="" can be used to clear the default skip list.

The variables

Defaults below are the ones the code applies, extracted from config.rs at build time. Where a variable has an alias, both names read the same setting and the newer name wins.

The broker is configured entirely through environment variables: 85 of them, listed below with the defaults the code actually applies. Booleans go through one strict parser: an unparseable value is a fatal boot error, while unset and empty both fall back to the default.

Server

Variable Type Default Also read as
PORT string 6632
QUEEN_APPLY_SCHEMA boolean true
QUEEN_MAX_BODY_BYTES integer 67108864 (64 MiB)

PostgreSQL

Variable Type Default Also read as
DB_POOL_SIZE integer 160
PG_DATABASE string postgres PG_DB
PG_HOST string localhost
PG_PASSWORD string postgres
PG_PORT integer 5432
PG_SSL_REJECT_UNAUTHORIZED boolean true
PG_USE_SSL boolean false
PG_USER string postgres
QUEEN_STMT_TIMEOUT_MS integer 30000

Authentication

Variable Type Default Also read as
JWT_ALGORITHM string HS256
JWT_AUDIENCE string (empty)
JWT_CLOCK_SKEW integer 30
JWT_ENABLED boolean false
JWT_ISSUER string (empty)
JWT_JWKS_REFRESH_INTERVAL integer 3600
JWT_JWKS_TIMEOUT_MS integer 5000
JWT_JWKS_URL string (empty)
JWT_PUBLIC_KEY string (empty)
JWT_ROLE_ADMIN string admin
JWT_ROLE_READ_ONLY string read-only
JWT_ROLE_READ_WRITE string read-write
JWT_ROLE_WRITE_ONLY string write-only
JWT_ROLES_ARRAY_CLAIM string roles
JWT_ROLES_CLAIM string role
JWT_SECRET string (empty)
JWT_SKIP_PATHS string /health,/metrics/prometheus,/metrics,/

Multi-broker mesh

Variable Type Default Also read as
QUEEN_CACHE_REFRESH_INTERVAL_MS integer 60000
QUEEN_MESH_PEERS string (empty)
QUEEN_MESH_PORT integer 6633 QUEEN_UDP_NOTIFY_PORT
QUEEN_SYNC_DEAD_THRESHOLD_MS integer 5000
QUEEN_SYNC_ENABLED boolean true
QUEEN_SYNC_HEARTBEAT_MS integer 1000
QUEEN_SYNC_SECRET string (empty)
QUEEN_UDP_NOTIFY_PORT integer 6633
QUEEN_UDP_PEERS string (empty)

Consume and long-poll

Variable Type Default Also read as
DEFAULT_TIMEOUT integer 30000 POP_DEFAULT_TIMEOUT_MS
POP_DEFAULT_TIMEOUT_MS integer 30000
POP_WAIT_BACKOFF_MULTIPLIER number 2.0
POP_WAIT_BACKOFF_THRESHOLD integer 3
POP_WAIT_INITIAL_INTERVAL_MS integer 100
POP_WAIT_MAX_INTERVAL_MS integer 1000

Storage engine

Variable Type Default Also read as
QUEEN_ACK_FUSION boolean true
QUEEN_ACK_FUSION_HOLD_MS integer 3
QUEEN_ACK_FUSION_SHARDS integer 8 QUEEN_V2_FUSION_SHARDS
QUEEN_ACK_REGISTRY boolean true
QUEEN_ACK_REGISTRY_MB integer 64
QUEEN_DEDUP_CACHE boolean true
QUEEN_DEDUP_CACHE_MB integer 512
QUEEN_HOTLIST boolean true
QUEEN_HOTLIST_IDLE_SWEEP_MS integer 300_000
QUEEN_HOTLIST_RESEED_MS integer 30000
QUEEN_HOTLIST_SHARDS integer 8 QUEEN_V2_FUSION_SHARDS
QUEEN_HOTLIST_WINDOW_BATCH integer 100
QUEEN_V2_FUSION_HOLD_MS integer 15
QUEEN_V2_FUSION_SHARDS integer 8
QUEEN_V2_ZSTD_LEVEL integer 3

Flow control

Variable Type Default Also read as
QUEEN_SEG_POP_INIT integer 16
QUEEN_SEG_POP_MAX integer 64
QUEEN_SEG_POP_MIN integer 4
QUEEN_SEG_PUSH_INIT integer 16
QUEEN_SEG_PUSH_MAX integer 64
QUEEN_SEG_PUSH_MIN integer 4
QUEEN_VEGAS_ALPHA number 3.0
QUEEN_VEGAS_BETA number 6.0

Background jobs

Variable Type Default Also read as
METRICS_FLUSH_MS integer 60000
METRICS_RETENTION_DAYS integer 90
PARTITION_CLEANUP_DAYS integer 30
QUEEN_PARTITION_CLEANUP_ENABLED boolean true
RETENTION_BATCH_SIZE integer 1000
RETENTION_INTERVAL integer 5000
STATS_INTERVAL_MS integer 10000

Durability spool

Variable Type Default Also read as
FILE_BUFFER_DIR string /var/lib/queen/buffers
FILE_BUFFER_EVENTS_PER_FILE integer 10000
FILE_BUFFER_FLUSH_MS integer 100
FILE_BUFFER_MAX_BATCH integer 100

Security

Variable Type Default Also read as
QUEEN_ENCRYPTION_KEY string (empty)
QUEEN_TENANCY_HEADER boolean false

Logging

Variable Type Default Also read as
LOG_LEVEL string info
QUEEN_LOG_JSON boolean false
QUEEN_LOG_RATES_MS integer 10000
QUEEN_LOG_TOPN_QUEUES integer 10
RUST_LOG string &env_str("LOG_LEVEL", "info

Experiment-only

These exist to run experiments against the storage engine. The source marks them as such, they are not part of any compatibility promise, and a deployment should not set them.

Variable Default Why it is not a product knob
QUEEN_V2_BUNDLE_MAX see notes fusion.rs: internal override only
QUEEN_V2_FUSION_MAX_INFLIGHT see notes fusion.rs: internal override only
QUEEN_V2_FUSION_MIN_FRAMES see notes fusion.rs: “a knob for experiments, not a product contract”
QUEEN_V2_FUSION_MIN_WAIT_MS see notes fusion.rs: “a knob for experiments, not a product contract”

Read but inert

The broker still parses these and still prints them in its boot configuration block, so they look live in a log. They change nothing.

Variable Default Status
QUEEN_V2_FUSION_FRAMES 500 kept for env compatibility; no longer a flush trigger (fusion.rs)
RETENTION_PARALLELISM 1 read and ignored; retention runs one bounded step at a time

Node identity

One variable does not appear in the table because it is not read through the same helper: QUEEN_SERVER_ID names this instance in mesh heartbeats and peer stats. Unset, the broker uses HOSTNAME; with neither, it generates queen-<8 hex>. The value is cosmetic (nothing routes on it), but it is what makes a peer list readable in the config: sync boot block.

Navigation

Type to search…

↑↓ navigate↵ selectEsc close