Database Modes
Preview environments often need varying levels of database isolation. Diverge provides four distinct database modes to fit your specific testing requirements and infrastructure constraints.
1. Shared Mode
Section titled “1. Shared Mode”Best for: Read-heavy workloads or completely stateless previews.
In Shared mode, the preview environment connects directly to the baseline (e.g., staging) database. No new database resources are provisioned.
2. Schema-Per-Env Mode (mode: schema)
Section titled “2. Schema-Per-Env Mode (mode: schema)”Best for: Standard pull request testing where schema migrations, relational constraints, and seed data are involved.
In this mode, Diverge provisions a new, isolated logical schema within your existing shared PostgreSQL cluster. This provides sub-second relational isolation without the overhead of spinning up new database compute instances.
Diverge’s SchemaDatabaseProvider handles the full lifecycle:
- Provision:
- Creates an isolated PostgreSQL schema named
preview_<env>(sanitized with hyphens converted to underscores, validated against^[a-z0-9][a-z0-9_-]*$) and an isolated per-schema role (diverge_preview_<schema>) whosesearch_pathis scoped topreview_<env>,public(with role passwords persisted durably in a managed Kubernetes Secretdiverge-db-role-<role>). - Base Tables, Sequences & Column Defaults (
LIKE public.<table> INCLUDING ALL): Automatically clones allpublicbase tables (CREATE TABLE IF NOT EXISTS preview_<env>.<table> (LIKE public.<table> INCLUDING ALL)), creates independent copies of allpublicsequences (information_schema.sequences), and re-mapsnextval('public.<seq>'::regclass)column defaults to referencepreview_<env>.<seq>. FOREIGN KEYConstraints (pg_constraint WHERE contype = 'f'): BecauseLIKE ... INCLUDING ALLdoes not copy foreign keys,SchemaDatabaseProviderqueriespg_constraint WHERE contype = 'f'(pg_get_constraintdef), automatically rewrites intra-schemaREFERENCES public.<table>(and unqualifiedREFERENCES <table>) references to point to the isolatedpreview_<env>.<table>tables, and applies them viaALTER TABLE preview_<env>.<table> ADD CONSTRAINT ....VIEWDefinitions (information_schema.views): Automatically clones allpublicviews frominformation_schema.views, rewritingpublic.table qualifiers topreview_<env>.viaCREATE OR REPLACE VIEW preview_<env>.<view> AS ....publicSchema Write-Protection: RevokesCREATE ON SCHEMA publicandINSERT, UPDATE, DELETE, TRUNCATE ON ALL TABLES IN SCHEMA publicfrom the preview role while granting read-only fallback (USAGEandSELECT), and verifies viahas_schema_privilege/has_table_privilegethat the preview role holds zero effective write orCREATEprivileges onpublic(catching unsafePUBLICpseudogroup grants before pods start).- Topologically Ordered
seedSourceData Seeding (spec.database.seedSource): Whenspec.database.seedSourceis set topublicorschema:<name>, Diverge copies rows across compatible writable non-generated columns (INSERT INTO ... OVERRIDING SYSTEM VALUE SELECT ... ON CONFLICT DO NOTHING) ordered topologically by foreign-key dependency count (pg_constraint WHERE contype = 'f' ASC) so parent tables are populated before child tables, and advances copied identity/serial sequences (pg_get_serial_sequence+setval). When set toconfigmap:<name>/<key>(default key:seed.sql), Diverge executes custom seed SQL from the referenced ConfigMap inside a transaction scoped toSET LOCAL search_path TO preview_<env>, public. - PgBouncer-Friendly Bounded Connection Pooling: Reuses a shared, bounded
*sql.DBpool per admin DSN (MaxOpenConns: 10,MaxIdleConns: 5,ConnMaxIdleTime: 5m,ConnMaxLifetime: 30m) with connection-levelsearch_path=preview_<env>,publicand transaction-scopedSET LOCAL search_path, preventing connection exhaustion when running behind PgBouncer or RDS Proxy. - Auto-Generated Connection Secret: When
spec.database.connectionRefis omitted inschemamode, the controller automatically creates (or updates) an owned KubernetesSecretnameddiverge-db-env-<env>-<hash8>in the preview namespace containingDATABASE_URL(the schema-scoped connection string) andDIVERGE_PREVIEW_SCHEMA(preview_<env>), and setsspec.database.connectionRefto reference it so migration Jobs and application pods consume the isolated schema automatically.
- Creates an isolated PostgreSQL schema named
- SetupSQL via Kubernetes Job: If
setupSQLis defined in the database configuration, Diverge provisions an ephemeral Kubernetes Job runningpsqlwithin the preview namespace to execute the initialization script:- Admin credentials are mounted securely via Secret reference (
DATABASE_URL). - The initialization SQL is mounted via a dedicated ConfigMap.
- The default container image is pinned by sha256 digest to
postgres:17-alpine(configurable via Helm atdatabase.setupJob.image). - Out-of-process execution ensures arbitrary SQL cannot compromise controller process memory or exhaust controller database pools.
- Admin credentials are mounted securely via Secret reference (
- Status: Queries
information_schema.schematato verify thepreview_<env>schema exists and monitors SetupSQL / migration Job completion. - Teardown: Drops the
preview_<env>schema withCASCADE, drops thediverge_preview_<schema>role, and deletes the associateddiverge-db-env-<env>-<hash8>anddiverge-db-role-<role>Secrets and Job resources.
3. Snapshot Mode
Section titled “3. Snapshot Mode”Best for: Testing against production-like datasets.
Snapshot mode clones data from a production or staging snapshot into a dedicated database instance for the preview environment. This provides the highest fidelity for data-dependent testing but can be slower to provision and consume more resources.
4. Fresh Mode
Section titled “4. Fresh Mode”Best for: Clean-slate testing and end-to-end integration tests.
Fresh mode provisions a completely new, empty database instance and executes your defined seed scripts or schema migrations to populate it. This ensures a consistent, predictable state for every preview environment.
