PostgreSQL
@bounda-dev/adapter-postgresql stores everything in PostgreSQL through
Postgres.js.
import { postgresql } from "@bounda-dev/adapter-postgresql";
postgresql({ url: process.env.DATABASE_URL! });postgresql({ host: "localhost", port: 5432, database: "shop", user: "shop", password: "…" });Options
Section titled “Options”| Option | Default | Meaning |
|---|---|---|
url |
A postgres:// connection URL |
|
host, port, database, user, password, ssl |
The same, as parts | |
schema |
public |
The schema that holds every Bounda table; created if missing |
tablePrefix |
bounda_ |
Put in front of every table Bounda creates |
maxConnections |
10 |
Size of the connection pool |
How it stores things
Section titled “How it stores things”positionin the events table is aBIGSERIAL. Every append takes a transaction-scoped advisory lock (pg_advisory_xact_lock) before writing, so positions are handed out in commit order and a reader of the global stream never sees a gap that a later commit would fill. The lock bounds write throughput to what one connection can commit; that is thousands of events per second, far above what the apps Bounda targets produce.- The stream version is checked in the same transaction as the write; a stale version rolls back
with a
ConcurrencyErrorand the command is retried with fresh state. - Handler claims are single
INSERT … ON CONFLICT DO UPDATE … RETURNINGstatements; due scheduled commands are taken withFOR UPDATE SKIP LOCKED. Any number of instances can run the worker role and each due command goes to exactly one of them. - Payloads and metadata are
jsonb; read-model booleans, dates and JSON fields useboolean,timestamp with time zoneandjsonb. Numbers aredouble precision.
Storage and read models opened from the same postgresql(...) share one pool, closed when the
app stops.
In tests
Section titled “In tests”The adapter’s own tests start postgres:17 with
Testcontainers; the same approach works for an app:
import { PostgreSqlContainer } from "@testcontainers/postgresql";import { createTestApp } from "@bounda-dev/core/testing";import { postgresql } from "@bounda-dev/adapter-postgresql";
const container = await new PostgreSqlContainer("postgres:17").start();const { app } = await createTestApp({ registry, adapter: postgresql({ url: container.getConnectionUri(), schema: "test" }),});