Skip to content

pgmem

Real PostgreSQL 18, in memory, for tests. No Docker, no disk. Prepare the schema once, share read-only tests, and give writing tests isolated copies in milliseconds.

The same schema, queries and per-test isolation, measured on one machine against the official image with docker run, Testcontainers, and a devbox-installed PostgreSQL.

Medians from 5 runs on one machine. Docker and Testcontainers memory uses 3 fresh OrbStack runs. Bars scale to the largest value in each card; lower is better.

Start to first query

From command start to TCP SELECT 1; downloads are excluded and Devbox uses an initialized cluster.

  • pgmem · Go library70 ms
  • Docker · PostgreSQL 181.65 s
  • Testcontainers · Go1.09 s
  • devbox · services up411 ms

Fresh copy per test

Median time to create an isolated database copy and run a join.

  • pgmem · Go library14 ms
  • Docker · PostgreSQL 1861 ms
  • Testcontainers · Go21 ms
  • devbox · services up83 ms

Indexed SELECT

Warm indexed SELECT over TCP.

  • pgmem · Go library34 µs
  • Docker · PostgreSQL 1893 µs
  • Testcontainers · Go102 µs
  • devbox · services up28 µs

Sort 200k rows

Median time to sort and count 200k rows.

  • pgmem · Go library120 ms
  • Docker · PostgreSQL 18259 ms
  • Testcontainers · Go258 ms
  • devbox · services up228 ms

Backend + test-process memory

After setup, before queries. Docker and Testcontainers sum container usage (PostgreSQL, plus Ryuk for Testcontainers) and benchmark-process growth. OrbStack VM changes are reported separately.

  • pgmem · Go library110 MiB
  • Docker · PostgreSQL 1877 MiB
  • Testcontainers · Go137 MiB
  • devbox · services up36 MiB

Initial download footprint

Same MB scale; Go link growth, compressed image layers, and devbox cache download measure different things.

  • pgmem · Go library37.9 MB
  • Docker · PostgreSQL 18117.9 MB
  • Testcontainers · Go120.0 MB
  • devbox · services up112.7 MB

Query latency, methodology and how to reproduce are on the benchmarks page.

The real thing

PostgreSQL 18.3 compiled to WebAssembly and translated to Go. Your SQL, planner behaviour and error codes are PostgreSQL’s, not an emulator’s.

Nothing to install

One dependency per language. No Docker daemon, no container runtime on CI, no files written to disk.

Share reads, isolate writes

Run migrations and seed data once, then share a fork across read-only tests and give writing tests isolated copies. Writing tests can run in parallel.

Any driver

pgmem listens on the PostgreSQL wire protocol, so pgx, psycopg, JDBC, node-postgres, ORMs and migration tools work unchanged.

s, err := pgmem.Start(ctx, pgmem.Options{Database: "app"})
if err != nil {
t.Fatal(err)
}
defer s.Close()
db, _ := sql.Open("pgx", s.DSN())