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.

VariableRequiredWhat it does
YEKE_DB_URLRequired for PG modePostgreSQL connection string (postgres://user:pass@host:5432/db). If unset, core uses SQLite.
YEKE_PG_POOL_SIZEOptionalPool 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_FILEOptionalPath 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:

  1. Core connects to PostgreSQL first (a plain connection).
  2. It checks the schema_migrations table read-only; if it does not exist, the install is "virgin".
  3. It reads the license (from file/env, and from the database record too once the schema exists).
  4. If the flag is missing: it fails with LICENSE_FEATURE_LOCKED without touching the schema at all. A virgin database stays virgin.
  5. 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-migrate tool.

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.