Skip to content

pg-dolly ​

A fresh Postgres database for every test, cloned from a template built once from your schema's SQL.

ts
import { 
readFile
} from 'node:fs/promises';
import {
PgDolly
} from 'pg-dolly';
// Once per test run const
dolly
= await
PgDolly
.
connect
();
const
template
= await
dolly
.
template
(await
readFile
('schema.sql', 'utf8'));
// For each test const
database
= await
template
.
clone
();
database
.
url
;
DollyDatabase.url: string

Connection URL: the server's URL, with this database's name.

// A test failed: keep its database to look at
database
.
keep
();
// At the end of the run: drops every clone not kept await
dolly
.
close
();

Get started →

Features ​

pg-dolly gives each test its own Postgres database. It builds a template from your schema once, and every test gets a copy of it (CREATE DATABASE … TEMPLATE), which takes a few milliseconds.

  • Tests run against a real database of their own, so they can commit, LISTEN, take locks and open several connections. Rolling back a transaction after each test rules all of that out.
  • The template is kept between runs, under a hash of the SQL, so it's only built again when the schema changes. See Speed.
  • It can share a server with your dev databases and with other test runs. It only ever drops databases it created, and parallel runs never see each other's. See How it works.
  • Bring your own migrations, client and test runner. It takes SQL (schema.sql, kept by pg-dolly-schema), and gives back a connection URL.
  • A failed test's database is kept so you can look at it. Everything else is dropped, including what a crashed run left behind.

Named after Dolly the sheep. The design follows Go's pgtestdb. The OpenAPI demo uses it for every test of its server.

Compared to ​

pg-dollyA transaction rolled back per testOne database, cleared between testsTestcontainersPGlite
Commits, NOTIFY, advisory locks, concurrent connections✅❌✅✅Limited (one connection)
Tests in parallel✅✅❌✅✅
Cost per testA database copyCheapestTruncating every tableA container, unless sharedAn in-process database
The real Postgres server✅✅✅✅Postgres in WebAssembly
NeedsA serverA serverA serverDockerNothing

See Why pg-dolly for the full comparison.