Engineering

A Portable Backup Format, Not pg_dump

Part four of building oo-workers in public: a schema-versioned NDJSON backup that survives a Postgres upgrade and bundles its S3 artifacts.

ObserveOne Team
2 min read

In this series

Building oo-workers in public

  1. 1.How We Built a Self-Hosted Monitoring Engine
  2. 2.Eight Monitor Types From One Engine
  3. 3.Building the Dashboard Without a Framework
  4. 4.A Portable Backup Format, Not pg_dump
  5. 5.A Three-Pass Code Audit in 14 PRs
  6. 6.Killing the 5-Second Poll
  7. 7.Cutting the Docker Image to 1.4 GB
  8. 8.Tests That Spin Real Databases
  9. 9.The Alert That Never Fired

With the engine and dashboard in place, operators needed to move an instance to a new host, recover one, or clone it for staging. So we built backup and restore, and chose not to lean on pg_dump.

Not pg_dump#

A dump is a portable, schema-versioned NDJSON stream that restores through the app's own schema, not a binary format. That buys three things pg_dump does not: it survives a Postgres major-version change, you can window the history (last 90 days, all of it, or config only), and it is plain text you can read.

What's in it#

Everything that defines an instance: every monitor type, its assertions, alert channels, status pages, regions, the admin login, and API keys with their hashes, so your login and keys keep working after a restore. Plus execution history, windowed to 90 days by default, and the QA Playwright script bodies that live in a DB column. Sessions are left out, so you log in again after restoring.

The artifacts problem#

The first version dumped the database only. But QA scripts, Playwright traces, and failure screenshots live in object storage, not the DB. Restore a database-only dump to a fresh host and the suites are unrunnable (their script pointers dangle) and every trace link 404s.

So a later release added an artifacts mode: a .oodump.tar.gz envelope (meta.json + dump.ndjson + artifacts/) that bundles every object in the bucket. Restore re-uploads them and rebuilds the index, so suites run on the new host. The toggle is on by default, and format auto-detection keeps the old database-only dumps restorable forever.

Restoring multi-GB without OOM#

A naive restore reads the whole archive into memory, which with artifacts can be many gigabytes. The restore streams the tar entry by entry instead: buffer the dump, then upload each artifact and discard it before reading the next. Peak memory drops from "the dump plus every artifact" to "the dump, or the single largest artifact, whichever is bigger."

Proving it#

A destructive round-trip test gates the format: back up, wipe, restore, then assert byte equality on the restored artifacts. A backup you have never restored is a guess, so the test restores for real.

Ready for AI-Powered Testing?

ObserveOne monitors your selectors 24/7 and automatically heals them when websites change. Never deal with broken tests again.

Start Free Trial