Skip to main content

Database configuration

[database]​

The PostgreSQL database the broker stores in, and how it connects.
[database]
# connection = "postgres://andromeda:andromeda@localhost:5432/andromeda"
platform_max_connections = 32
write_reserve_percent = 25
acquire_timeout = "5s"
synchronous_commit = "on"

database.connection​

URL or tablerestart to applysensitive

The PostgreSQL server and the default tenant's database, as a connection URL or as a table of its parts. It has no default: set it here or in ANDROMEDA__DATABASE__CONNECTION, or each part in its own variable such as ANDROMEDA__DATABASE__CONNECTION__PASSWORD. It always names PostgreSQL itself, never a proxy: tenant creation, migrations and maintenance connect here even when database.pooler is set, and so do requests when it is not.

Required
Yes. Example: "postgres://andromeda:andromeda@localhost:5432/andromeda"
Sensitive
configuration show replaces the value.
Environment variable
ANDROMEDA__DATABASE__CONNECTION

database.platform_max_connections​

positive integerrestart to apply

The most connections the platform pool opens, in each broker process. It reads and writes the tenant registry every tenant load consults, the schedule of tenants with due work and the routes of forwarded subscriptions, and always connects to database.connection, even when database.pooler is set. Tenants size their own pools with tenancy.default_tenant.max_connections and tenancy.databases.max_connections.

Default
32
Must be
0 < platform_max_connections
Environment variable
ANDROMEDA__DATABASE__PLATFORM_MAX_CONNECTIONS

database.write_reserve_percent​

integerrestart to apply

The percentage of each tenant pool that read requests (queries, retrievals, discovery and temporal reads) never hold, so writes always find a connection however many reads queue. Rounded down to whole connections: a pool too small to spare one keeps every connection for reads.

Default
25
Must be
write_reserve_percent < 100
Environment variable
ANDROMEDA__DATABASE__WRITE_RESERVE_PERCENT

database.acquire_timeout​

non-zero durationrestart to apply

How long a request waits for a free database connection before it is answered 503 with Retry-After.

Default
"5s"
Must be
0 < acquire_timeout < request_limits.timeout
Environment variable
ANDROMEDA__DATABASE__ACQUIRE_TIMEOUT

database.synchronous_commit​

stringrestart to apply

The PostgreSQL synchronous_commit level set on the default tenant's database and every tenant database. It is installed with ALTER DATABASE ... SET, so every session inherits it, including sessions a transaction-pooling proxy hands out. With "off", a server crash can lose writes clients were already told succeeded.

Default
"on"
Allowed values
"on"Acknowledge a commit once its WAL is flushed to disk, and on synchronous standbys when any are configured.
"off"Acknowledge a commit before its WAL is flushed. Ingest is faster, but a server crash loses the transactions acknowledged in the last three times wal_writer_delay, and notifications for them may already have gone out.
"local"Wait for the local WAL flush only, never for synchronous standbys.
"remote-apply"Wait until synchronous standbys have applied the WAL, so a read on a standby sees the commit.
"remote-write"Wait until synchronous standbys have handed the WAL to their operating system, without waiting for it to reach disk.
Environment variable
ANDROMEDA__DATABASE__SYNCHRONOUS_COMMIT

[database.pooler]​

A transaction-pooling proxy, such as PgBouncer in transaction mode, on the request path. Left out, every connection goes straight to database.connection.
# [database.pooler]
# connection = "postgres://andromeda:andromeda@localhost:6432/andromeda"
# max_connections_per_tenant = 2

database.pooler.connection​

URL or tablerestart to applysensitive

The proxy's connection, as a URL or as a table of its parts, used by requests in place of database.connection. The proxy forwards to the same PostgreSQL, so it normally differs from database.connection only in host and port. Tenant creation, migrations and maintenance keep connecting to database.connection.

Required
Yes. Example: "postgres://andromeda:andromeda@localhost:6432/andromeda"
Sensitive
configuration show replaces the value.
Environment variable
ANDROMEDA__DATABASE__POOLER__CONNECTION

database.pooler.max_connections_per_tenant​

positive integerrestart to apply

The connections each named tenant's pool opens through the proxy, in place of tenancy.databases.max_connections. Keep it small: the proxy multiplexes every tenant onto its own backends, so a tenant needs only enough for its concurrent requests, and many loaded tenants do not exhaust the host's ports.

Required
Yes. Example: 2
Must be
0 < max_connections_per_tenant ≤ tenancy.databases.max_connections
Environment variable
ANDROMEDA__DATABASE__POOLER__MAX_CONNECTIONS_PER_TENANT

[database.name_cache]​

The in-memory caches of each tenant's attribute and entity type names.
[database.name_cache]
loading = "eager"
max_size_per_dictionary = "16 MiB"
idle_eviction_after = "8h"

database.name_cache.loading​

stringrestart to apply

When the caches are filled: as the tenant is loaded, or as names are first resolved.

Default
"eager"
Allowed values
"eager"Read every stored name into the caches when the tenant is loaded, so its first requests resolve names from memory.
"lazy"Read a name into its cache the first time it is resolved.
Environment variable
ANDROMEDA__DATABASE__NAME_CACHE__LOADING

database.name_cache.max_size_per_dictionary​

non-zero sizerestart to apply

The memory each of a tenant's two name caches may hold, in each broker process. A tenant holds at most twice this, and only as much as it has resolved. When a cache is full the least valuable names are dropped; a dropped name is read back from the database the next time it is resolved, so a full cache costs reads but never refuses a write.

Default
"16 MiB"
Must be
0 < max_size_per_dictionary
Environment variable
ANDROMEDA__DATABASE__NAME_CACHE__MAX_SIZE_PER_DICTIONARY

database.name_cache.idle_eviction_after​

string or durationrestart to apply

How long a cached name may go unused before it is dropped, or "unlimited" to drop names only when a cache is full.

Default
"8h"
Allowed values
"unlimited"No limit.
Must be
0 < idle_eviction_after
Environment variable
ANDROMEDA__DATABASE__NAME_CACHE__IDLE_EVICTION_AFTER

[database.maintenance]​

The adaptive PostgreSQL inspection and maintenance controller.
[database.maintenance]
mode = "automatic"
profile = "conservative"
repack = "reported"
max_repack_size = "4 GiB"

database.maintenance.mode​

stringrestart to apply

Whether maintenance is off, only inspects and reports, or also acts on what it finds. Acts by default, so a deployment nobody tunes still gets its wraparound and WAL retention warnings, its catch-up vacuums and its index rebuilds. An action whose right the broker's role lacks is only reported. Set "observe" where the database is maintained on its own schedule.

Default
"automatic"
Allowed values
"disabled"Do not run the controller.
"observe"Inspect the databases and report the maintenance the controller decides on, without carrying any of it out.
"automatic"Inspect the databases and carry out the maintenance the controller decides on.
Environment variable
ANDROMEDA__DATABASE__MAINTENANCE__MODE

database.maintenance.profile​

stringrestart to apply

How often the controller inspects, and how much evidence it needs before it acts.

Default
"conservative"
Allowed values
"conservative"Inspect less often and require stronger evidence before acting.
"responsive"Inspect more often and react to smaller signs of degradation.
Environment variable
ANDROMEDA__DATABASE__MAINTENANCE__PROFILE

database.maintenance.repack​

stringrestart to apply

Whether automatic maintenance also runs the online repacks of bloated tables it decides on, or only reports them. A repack copies the table while it stays in use, so the database needs free disk of up to twice the table's size, which the broker cannot measure. Repacks are only reported by default, so their decisions can be checked against the free disk first. In observe mode repacks are reported whatever this says.

Default
"reported"
Allowed values
"reported"Decide repacks and report them as would-act, without running any.
"performed"Run the repacks the controller decides on while database.maintenance.mode is "automatic".
Environment variable
ANDROMEDA__DATABASE__MAINTENANCE__REPACK

database.maintenance.max_repack_size​

string or sizerestart to apply

The largest table, its heap plus its TOAST, the controller repacks, or "unlimited" to repack a table of any size.

Default
"4 GiB"
Allowed values
"unlimited"No limit.
Must be
0 < max_repack_size
Environment variable
ANDROMEDA__DATABASE__MAINTENANCE__MAX_REPACK_SIZE