If you want to use a managed PostgreSQL database for self-hosted 3B, follow this guide to prepare it for 3B v6+. Use the Helm chart on your Kubernetes cluster, including k3s. The single-server installer (bootstrap.sh and setup.sh) uses bundled PostgreSQL and does not currently support an external database.
Configure the database
Use PostgreSQL 18 and connect to the writer endpoint. Zero needs a direct connection that supports the PostgreSQL replication protocol.
Enable logical replication through your provider’s settings and verify
wal_level=logical. Allow enoughmax_replication_slotsandmax_wal_sendersfor Zero and any other replication consumers.Add
pg_stat_statementstoshared_preload_libraries, keeping any existing libraries, and apply the required reboot.
Configure the roles
Connect to the server’s postgres database as an administrator using psql. For a fresh installation, create a dedicated login and the databases below. The \password command prompts for the login’s password; save it for the Kubernetes secret:
CREATE ROLE tines LOGIN; \password tines CREATE DATABASE "3b" OWNER tines; CREATE DATABASE zero_internal OWNER tines;
Run migrations as tines so it owns the application objects. Grant it logical replication access through PostgreSQL’s REPLICATION attribute or your provider’s equivalent.
Role | Purpose |
| Login for 3B, migrations, and Zero replication |
| 3B’s internal query role; inherits |
For a fresh installation where app_runtime does not exist, have the administrator run:
CREATE ROLE app_runtime NOLOGIN INHERIT; GRANT pg_read_all_data, pg_write_all_data TO app_runtime WITH INHERIT TRUE; GRANT app_runtime TO tines WITH SET TRUE, INHERIT FALSE;
3B checks app_runtime during setup and skips role changes when it already matches. Keep this role limited to the memberships above, without superuser, replication, or BYPASSRLS attributes. Roles are shared across databases, so account for the data roles’ scope if other applications share the server.
The same login can own zero_internal if your deployment uses a separate database for Zero’s internal storage. A separate login is optional; it needs to own and manage those objects, but does not need replication privileges.
zero-admin-password is an HTTP administration secret, not a database password; it does not create a database role.
Install the extension
We recommend pg_stat_statements 1.12. Pre-installed 1.11 is also supported.
Connect to 3b as the database administrator and check the available versions. If the extension is absent, install it before starting 3B, using VERSION '1.11' instead if 1.12 is unavailable:
SELECT version FROM pg_available_extension_versions WHERE name = 'pg_stat_statements'; CREATE EXTENSION pg_stat_statements VERSION '1.12';
3B preserves an installed version. Otherwise, the PostgreSQL 18 fresh-install migration requests 1.12, so pre-installing 1.11 is required where 1.12 is unavailable.
Connect 3B with Helm
Before running helm install, create db-credentials in the release namespace using the tines password and writer endpoint. Include all four keys: password, url, host-url-zero-internal, and a separately generated zero-admin-password.
Set postgres.enabled: false in your values file and follow the external-database appendix in the Helm installation guide for the secret creation command. Both databases and the secret must exist before installation.
Schema changes and failover
3B and Zero manage their publications using explicit table lists. You do not need to pre-create a publication or grant privileges for FOR ALL TABLES or FOR TABLES IN SCHEMA.
Zero also creates event triggers, which require PostgreSQL superuser privileges or a provider-supported equivalent. Without event-trigger access at first startup, Zero can fall back to full replica and client resets after schema changes. Contact Tines Support before using that setup in production. Keep event-trigger privileges during upgrades; revoking them later can break trigger updates.
Test a schema-changing upgrade and writer failover before production. Confirm that Zero reconnects and clients receive changes. A lost or invalidated replication slot can require a replica rebuild. Monitor replication progress and retained WAL using Postgres monitoring.
AWS Aurora and RDS
On AWS, we recommend Aurora PostgreSQL for its high availability and continuous backups with point-in-time recovery. Use the cluster writer endpoint and include an Aurora Replica in a different Availability Zone for failover. Amazon RDS for PostgreSQL is an alternative when cost is the priority; it also supports point-in-time recovery.
Create the Aurora cluster or RDS instance before installing 3B, with network access from your Kubernetes cluster. In the AWS console’s credential settings, choose a master username and either set the password yourself or select “Auto generate a password”. After creation, use “View credential details” to save an auto-generated password; AWS shows it once. If you choose Secrets Manager-managed credentials, retrieve the password from that secret instead.
Use these master credentials for the administrator setup above. The Kubernetes secret uses the password you set for tines.
Set rds.logical_replication=1 in the AWS parameter group (the DB cluster parameter group for Aurora), configure shared_preload_libraries there, and apply the required reboot. See AWS’s setup instructions for RDS or Aurora.
Have your AWS database administrator grant:
GRANT rds_replication, rds_superuser TO tines;
rds_replication allows slot management and streaming. rds_superuser grants broader administrative access needed for Zero’s event triggers.
Aurora’s pg_stat_statements 1.11 is supported. Install it before starting 3B if 1.12 is unavailable; check AWS’s extension versions.
