yeke.io · docs · enterprise
PostgreSQL Connection
YEKE uses SQLite by default. Enterprise can connect to an existing PostgreSQL server. This guide covers connection settings, the snapshot key and licensing requirements.
Overview
Two drivers, one switch.
Set YEKE_DB_URL to use PostgreSQL. Otherwise, core uses the SQLite file at YEKE_DB_PATH. Setting both prevents startup. If PostgreSQL is unavailable, core stops with an error rather than falling back to SQLite.
PostgreSQL is used with the same type discipline as SQLite across the entire SQL surface: dates as ISO-8601 text, booleans as 0/1, JSON as text. The one difference that matters to your DBA is the connection shape: §3 below.
Setting up the connection
One environment variable, plus an optional CA file.
| Variable | Required | What it does |
|---|---|---|
YEKE_DB_URL | Required for PG mode | PostgreSQL connection string (postgres://user:pass@host:5432/db). If unset, core uses SQLite. |
YEKE_PG_POOL_SIZE | Optional | Pool size per replica, default 10. The right value is a conversation with your DBA; YEKE cannot know your organization's pooling policy. |
YEKE_DB_CA_FILE | Optional | Path to a CA file if the server certificate is signed by your own internal CA. sslmode=disable is not rejected — this connection is your own database network, and TLS-free internal PostgreSQL setups are a legitimate organizational standard. |
kubectl -n yeke-system create secret generic yeke-core-secrets \ --from-literal=YEKE_DB_URL="postgres://<user>:<password>@<pg-host>:5432/<db>" \ --from-literal=YEKE_SNAPSHOT_KEY="$(openssl rand -hex 32)"
No server configuration is required: everything the driver uses is a standard client capability (plain SQL, TLS, advisory locks). No extensions need to be installed.
Supported connection shape
The shape of the connection target is a contract; connecting to a corporate PostgreSQL through a pooler is the norm, not the exception.
YEKE_DB_URL must point at the postmaster directly or at a
session-mode pooler.
transaction/statement-mode pooling is not supported
With PgBouncer, use a dedicated session-mode pool or connect directly to PostgreSQL. Leader-election advisory locks and session settings require a persistent connection. transaction and statement pooling are not supported.
The startup probe catches this mismatch early: if the connection target does not have this shape, core stops with an explicit error rather than misbehaving silently.
Minimum version and pool
The floor is a support-policy boundary, not a technical one.
PostgreSQL 15 or later is supported. Set YEKE_PG_POOL_SIZE to configure the pg.Pool connection pool; the default is 10 connections per replica.
Snapshot key
Optional in SQLite mode, required in PostgreSQL mode.
The 32-byte YEKE_SNAPSHOT_KEY that encrypts stored credentials, AI keys, and
hook secrets is generated by core itself and written to the data directory if you leave it
unset in SQLite mode. PostgreSQL mode has no such fallback — core does not generate the
key, and it must be supplied externally through YEKE_SNAPSHOT_KEY (env) or
YEKE_SNAPSHOT_KEY_FILE (file path). On Kubernetes this is a Secret — the example
command in §2 above creates both together.
The reason is filesystem independence: in PostgreSQL mode core expects no directory to exist or be writable — having it generate and write a key to one would undo that independence from the start.
License gate: ha-postgres
What is gated is not multi-replica — it is the PostgreSQL connection itself.
The PostgreSQL driver sits behind the Enterprise ha-postgres feature — even a
single-replica PostgreSQL setup requires this flag; there is no separate flag for it. The
startup order is deliberate:
- Core connects to PostgreSQL first (a plain connection).
- It checks the
schema_migrationstable read-only; if it does not exist, the install is "virgin". - It reads the license (from file/env, and from the database record too once the schema exists).
- If the flag is missing: it fails with
LICENSE_FEATURE_LOCKEDwithout touching the schema at all. A virgin database stays virgin. - If the flag is present: normal startup (baseline/migrations) proceeds.
If the schema was already created by a previous startup, core never drops it — the objects in your database are yours; if the license flag is removed later, the error states that the schema is left in place and cleanup is your organization's call.
0.26.1 note: on an older install that has no archive table
(archived_operations), migration 38 no longer fails — if the table is missing it
skips that step and core starts; behaviour is unchanged when the table IS present. If the
table is missing, the startup log prints one line saying so, on EVERY startup until the
install is fixed. On the same install, the compliance
report no longer errors: it declares the archive as "unreadable" and keeps being produced
from live records. Do not turn on
YEKE_RETENTION_ARCHIVE until the table is
fixed — archive writing stops with archive_stalled.
Limits
YEKE is the side that connects, not the side that operates.
- YEKE does not install, cluster, back up, or operate PostgreSQL. It connects to a PostgreSQL your organization provides — its version, clustering, replication, backup policy, and tuning are your DBA's discipline.
- No server configuration is required. No extension installs or special GUC settings are needed.
- There is no PostgreSQL in Community. SQLite is, and remains, the first-class path for Community and single-node installs.
- Manually moving an existing SQLite install is not supported. The supported path
is the
yeke-migratetool.
Have an existing SQLite install?
Connecting to PostgreSQL does not automatically move an existing SQLite install. The
supported path is the yeke-migrate tool: offline, one-way, with integrity
verification.