Compatibility
Driver, error, and transaction results for postgres.js, node-postgres, Bun.sql, and PGlite.
The same suite runs against postgres.js, node-postgres, Bun.sql, and PGlite. pass means the case ran and matched. skip means the adapter does not offer that behaviour. fail means it ran and did not match. not-run means the suite did not reach it. The command is okm driver test. The cells below are generated from tests/driver-suite.test.ts and tests/error-suite.test.ts. The floor is Minimum Postgres.
Supported majors are Postgres 15, 16, 17, and 18. The floor is 15: Postgres 13 is past end of life, 14 ends in November 2026, and 15 gives us features we can use later. connect() refuses an older server with OKM1803. minPostgres is 15, 16, 17, or 18. requires: { postgres: ">=17" } is the same floor and is deprecated. Identity columns need Postgres 10. A bare t.id() stores gen_random_uuid(), which is built in from Postgres 13. An explicit uuidv7() needs Postgres 18. A pull request runs Postgres 18 when the diff touches dialects, migrate, or runtime. bun run verify runs the suite on this machine. A push to main, the nightly run, and a release cover each supported major. A failure on an older major in this list stays in the run.
Postgres: native. Since 18. Proof passes (proof:type.uuidv7).
PGlite runs in the check job. The in-process wire server runs in the check job. postgres.js, node-postgres, and Bun.sql run in the postgres job (REQUIRE_DOCKER=1). Bun.sql runs only under Bun. A skip means the adapter did not declare the capability that case needs. node-postgres and Bun.sql do not describe a statement without running it. Bun.sql does not surface RAISE NOTICE and does not abort an in-flight statement. PGlite has no socket to cut, so COMMIT loss (r2.commit-loss, r2.batch-commit-loss) is unsupported in okm driver test, with that reason. It is not a silent skip.
Neon is not a column in this table. postgres.js and node-postgres pointed at Neon endpoints are not columns either, and those results stay unclassified. okmodel/pg/neon has its own connect gate. It is checked locally when its credentials are set and skipped in CI. WebSocket mode is interactive. HTTP mode is transactions: "batch": tx() is refused. A transaction-mode pooler does not promise session state. COMMIT loss is unsupported (no socket to cut) because the harness cut is a TCP relay. A result that never arrives is still outcome_unknown.
| Case | postgres.js | node-postgres | Bun.sql | PGlite |
|---|---|---|---|---|
| execute returns rows | pass | pass | pass | pass |
| keeps null as null | pass | pass | pass | pass |
| keeps timestamps as wire text | pass | pass | pass | pass |
| keeps numeric as wire text | pass | pass | pass | pass |
| keeps bigint as wire text | pass | pass | pass | pass |
| keeps json as wire text | pass | pass | pass | pass |
| keeps arrays as wire text | pass | pass | pass | pass |
| returns notices | pass | pass | skip | pass |
| batch commits every statement | pass | pass | pass | pass |
| batch rolls back a failure at each position | pass | pass | pass | pass |
| batch reports a deferred constraint at commit | pass | pass | pass | pass |
| rejects a pre-aborted signal before the statement | pass | pass | pass | pass |
| cancels an in-flight statement | pass | pass | skip | skip |
| times out an in-flight statement | pass | pass | skip | skip |
| cancels a batch and rolls it back | pass | pass | skip | skip |
| times out a batch and rolls it back | pass | pass | skip | skip |
| runs a batch inside a transaction on a savepoint | pass | pass | pass | pass |
| clears a custom setting and an advisory lock on release | pass | pass | pass | pass |
| reports pool stats | pass | pass | pass | pass |
| close rejects a later execute | pass | pass | pass | pass |
| acquire timeout is OKM1846 and does not use another pool | pass | pass | pass | pass |
| describes a statement | pass | skip | skip | pass |
| streams rows | pass | pass | pass | skip |
| delivers a notification | pass | pass | pass | pass |
| maps a unique violation | pass | pass | pass | pass |
| maps a not-null violation | pass | pass | pass | pass |
| maps a check violation | pass | pass | pass | pass |
| maps a foreign key violation | pass | pass | pass | pass |
| maps an exclusion violation | pass | pass | pass | pass |
| maps serialization, deadlock, and lock timeout | pass | pass | pass | pass |
| maps a statement timeout | pass | pass | pass | pass |
| maps an in-flight statement timeout | pass | pass | skip | skip |
| maps a cancelled call and does not retry it | pass | pass | pass | pass |
| maps a connection failure | pass | pass | pass | pass |
| carries batchIndex on a batch failure and null at commit | pass | pass | pass | pass |
The public type surface (scripts/api-surface.ts) and the consumer fixtures (*.test-d.ts files the required typecheck includes) compile with TypeScript 7.0.2 (tsc, required, bun run typecheck). The same files compile with TypeScript 6.0.3 through the dev-only typescript-editor package (bun run ts6:check). That run is not part of bun run check. Nothing in src/ imports the TypeScript compiler API. TypeScript 7.0 has no stable programmatic API until 7.1.
| Next | You use it for |
|---|---|
| Drivers | Pick a driver and a prepared mode. |
| Minimum Postgres | What PostgreSQL 15 through 18 can run. |
| driver test | Run the suite that fills this table. |