BuildWithMatija
Get In Touch
Build with Matija logo

Build with Matija

Modern websites, content systems, and AI workflows built for long-term growth.

Services

  • Headless CMS Websites
  • Next.js & Headless CMS Advisory
  • AI Systems & Automation
  • Website & Content Audit

Resources

  • Case Studies
  • How I Work
  • Blog
  • CMS Hub
  • E-commerce Hub
  • Dashboard

Headless CMS

  • Payload CMS Developer
  • CMS Migration
  • Payload vs Sanity
  • Payload vs WordPress
  • Payload vs Contentful

Get in Touch

Ready to modernize your stack? Let's talk about what you're building.

Book a discovery callContact me →
© 2026Build with Matija•All rights reserved•Privacy Policy•Terms of Service
  1. Home
  2. Blog
  3. Tools
  4. DBLab: Save €55/mo with PostgreSQL Instant Clones Now

DBLab: Save €55/mo with PostgreSQL Instant Clones Now

Use DBLab's ZFS-powered PostgreSQL cloning on a €5 Hetzner VPS to replace Neon branching, get one-second dev clones…

24th April 2026·Updated on:2nd May 2026·MŽMatija Žiberna·
Tools
DBLab: Save €55/mo with PostgreSQL Instant Clones Now

📚 Get Practical Development Guides

Join developers getting comprehensive guides, code examples, optimization tips, and time-saving prompts to accelerate their development workflow.

No spam. Unsubscribe anytime.

I Was Paying €60/Month for a Dev Database. Here's the Open-Source Alternative I Found.

You can replace Neon's database branching with a self-hosted DBLab Engine on a €5/month Hetzner VPS and get the same workflow — instant clones from production data, per-developer isolation, and one-second resets — for a fraction of the cost. This guide walks through how DBLab works, why it replaces the specific Neon feature I actually used, and what the daily workflow looks like in a Payload CMS project.


The €60 wake-up call

When I started building projects on Vercel, Neon was the obvious database choice. Free tier, zero config, managed PostgreSQL — what's not to love? The developer experience was genuinely great. You get database branching, instant clones for development, and you never think about infrastructure.

Then my projects started getting real traffic.

The first month the bill crossed €40, I noticed. By the time it climbed past €60 for a single PostgreSQL instance, I started asking questions. The price wasn't unreasonable for a managed service — Neon is doing a lot of infrastructure work behind the scenes. But I knew what I was actually using out of all of it:

  • A PostgreSQL database
  • The ability to branch it for development
  • The ability to reset branches to a clean state

That's it. I wasn't using serverless scale-to-zero. I wasn't using the HTTP query API. I was paying managed-service rates for a workflow that should, in theory, be possible to self-host. So I went looking.


What I actually needed from Neon

Before diving into alternatives, I had to be honest about which Neon feature I was paying for. Neon does a lot of things — serverless connection pooling, autoscaling compute, pay-per-second billing, a custom storage engine. Most of that is infrastructure complexity I don't need.

The feature I couldn't live without was this: I have a production database. I create a dev branch from it — instantly, regardless of database size. My dev environment connects to the branch instead of production. I break things, run migrations, and mess with data freely. Then I reset back to the production baseline whenever I want.

Once you've had that workflow, sharing a single staging database with your team feels like going back to FTP deploys. The question was whether there's an open-source way to get exactly this on my own VPS.


Enter DBLab

The answer turned out to be DBLab (Database Lab Engine), an open-source tool from postgres.ai.

DBLab does one thing: instant PostgreSQL cloning using ZFS thin provisioning.

It runs as a Docker container on your VPS. It uses ZFS — a filesystem with built-in copy-on-write snapshotting — to create thin clones of your PostgreSQL data directory. A thin clone shares all the underlying data blocks with the original snapshot and only stores what changes. Creating a clone of a 100 GB database takes the same 1–2 seconds as cloning a 100 MB one. No full copy. No waiting. Just a new, running PostgreSQL instance that looks exactly like production.


The mental model that makes it click

The most important thing to understand about DBLab is this: it is a photocopier, not a proxy.

Your production database keeps running exactly as it always has. Your app keeps connecting to it directly. DBLab is not in the production path. It doesn't sit between your app and your database. It doesn't touch production writes.

PRODUCTION
  Your App → prod PostgreSQL (Neon / Supabase / RDS / self-hosted)
                │
                └── pg_dump (read-only, one-way copy)
                        │
                        ▼
DBLAB (your VPS)
  snapshot of prod data (ZFS)
        │
        ├── clone → developer A  (port 6000)
        ├── clone → developer B  (port 6001)
        └── clone → CI pipeline  (port 6002)

DBLab pulls a read-only copy of your production data — once, or on a schedule. After that, it works entirely from the local copy. There is no ongoing connection back to production. Production doesn't know DBLab exists.

The worst thing that can happen on a DBLab clone — dropping every table, corrupting data, running a catastrophic migration — affects only that clone. You reset it in one second. Production is untouched.


The vocabulary of branching

If you're coming from Git, these terms feel familiar, but they work slightly differently when you're talking about gigabytes of raw database files. Here is how DBLab and ZFS think about them.

A snapshot is a static, read-only photo of your data at a specific moment. It takes up almost zero space because it just marks which blocks of data existed at that time. You cannot connect to a snapshot from your app.

A branch is a logical pointer. When you create a dev branch, you're naming a snapshot so you can find it later.

A clone is the actual running database — the living thing. When you create a clone, DBLab takes a snapshot and makes a thin copy of it that you can connect to and write to. This is where you run your migrations.

TermWhat it isWritable?Analogy
SnapshotPoint-in-time data❌ NoA photo
BranchA named reference❌ NoA Git tag
CloneA running process✅ YesA photocopy

What a real dev morning looks like

I run Payload CMS with Next.js. Here's my actual daily workflow now.

# 1. Create a clone from the dev branch — takes ~2 seconds
dblab clone create --branch dev --id matija --username appuser --password secret
# → DBLab returns: host=my-vps port=6000

That connection string goes straight into my local environment:

DATABASE_URI=postgres://appuser:secret@my-vps:6000/mydb

My app starts locally and connects to the DBLab clone — which has real production data, real schema, real content. Not seed data. Not a months-old staging copy. Actual prod.

# Test a Payload migration against real production data
payload migrate

# Something broke? Reset to baseline in 1 second
dblab clone reset matija

# Works? Run it on prod with confidence
payload migrate --env production

That last step is the entire point. Running the migration on production after proving it works on a clone with real prod data means no more "it worked on my machine with seed data."


How connection strings work

When you create a clone, DBLab spins up a real PostgreSQL container, assigns it a port from a pool (6000–6099 by default), and gives you a connection string. You put that in .env.local. Your dev app connects to it like any other PostgreSQL.

EnvironmentWho issues the stringExample
ProductionYour DB host (Neon, Supabase, RDS)postgres://user:pass@prod-host:5432/mydb
DevelopmentDBLab, when you create a clonepostgres://appuser:secret@your-vps:6000/mydb

Each developer gets their own clone on their own port. No shared dev database. No stepping on each other's changes.

DeveloperClone IDPort
Alicealice-dev6000
Bobbob-dev6001
CI job #123ci-pr-1236002

Each clone is independent, disposable, and costs almost no extra disk space thanks to ZFS copy-on-write.


Why this beats a shared staging database

Before DBLab, the standard answer was "use a staging database." Here's why that never actually worked well.

Staging DBDBLab clone
Shared across teamYes — one person's migration breaks everyoneNo — one per developer
Reset to prod stateManual, coordinated, often forgotten1 second, any time, self-service
Creation timeDays of setup and coordination2 seconds
Drift from productionConstant — staging gets stale fastZero — always based on latest snapshot
Cost modelAlways running, always driftingExists only when needed

The honest comparison: Neon vs. self-hosted DBLab

DBLab doesn't replace everything Neon does. Neon is a managed database platform doing a lot more than branching. Here's the honest picture:

FeatureNeonDBLab (self-hosted)
Database branching✅ Built-in✅ Via ZFS snapshots
Instant clone/reset✅✅
Serverless scale-to-zero✅❌ Not applicable
HTTP query API✅❌
Connection pooling✅ Built-in (PgBouncer)❌ Add your own
Pay-per-second billing✅❌ Fixed VPS cost
Zero infrastructure management✅❌ You manage it
Data stays on your infra❌ Neon's cloud✅ Your VPS
Monthly cost (my usage)€40–60+ and growing~€5 fixed (Hetzner VPS)
Open source, self-hostablePartially (not practical)✅ Fully

If you need serverless PostgreSQL, Neon is still the right tool. If what you actually use is the branch-and-reset workflow — and you want it on your own infrastructure with predictable costs — DBLab is the open-source answer.


What it runs on

Everything runs in Docker on a single VPS:

ContainerRole
postgresai/dblab-serverThe engine — manages ZFS snapshots, branches, clones
postgresai/ce-uiWeb UI for managing clones in a browser
postgresai/extended-postgres:17Spun up per clone, destroyed when done
nginxReverse proxy for the UI

The only host-level requirement is ZFS, which ships in the standard Ubuntu 24 package repository. Everything else is containerized.


The setup at a glance

I won't walk through every step here — the full setup guide is in the repo — but the high-level flow is:

  1. Get a VPS — Ubuntu 24, Docker installed, a spare disk or partition for ZFS
  2. Install ZFS — apt install zfsutils-linux, create a pool
  3. Configure the source — Point DBLab at your production PostgreSQL via connection string in .env
  4. Start the engine — make up — it pulls a logical dump from your source automatically
  5. Create branches — dblab branch create main, then dblab branch create --parent-branch main dev
  6. Create clones — dblab clone create --branch dev --id my-clone --username appuser --password secret

From that point on, clones are created in seconds, reset in seconds, and production is never touched.

# The full lifecycle in 30 seconds
dblab clone create --branch dev --id test --username dev --password dev
# → port 6000, connect your app

dblab clone reset test
# → back to clean state, 1 second

dblab clone destroy test
# → gone, resources freed

What I gave up (and what I didn't miss)

Switching from Neon to DBLab meant giving up zero infrastructure management — I now maintain a VPS. In practice, that's one Docker Compose file and a ZFS pool. It took an afternoon to set up and hasn't needed attention since.

I also gave up serverless scaling, but my production database still runs on its managed host. DBLab is only for the dev and test clones, which don't need autoscaling. And yes, I gave up the Neon dashboard — DBLab has its own web UI. It's simpler, but it does what I need.

What I gained is predictable costs. €5/month for a Hetzner VPS instead of €60+/month and climbing. My production data copy lives on my VPS rather than transiting through a third-party branching service. And there's no vendor lock-in — it's standard PostgreSQL on standard ZFS. If DBLab disappeared tomorrow, the data is still there in a ZFS dataset.


FAQ

Does DBLab work with any PostgreSQL host, or only Neon? It works with any PostgreSQL host — Supabase, RDS, self-hosted, or Neon itself. DBLab only needs a connection string to pull the initial logical dump. What your production database runs on is irrelevant to DBLab.

How fresh is the data in my clone? As fresh as your last sync. You configure the sync schedule in the DBLab config — hourly, daily, or on-demand. Most workflows are fine with a nightly sync.

Can multiple developers use the same DBLab instance? Yes. Each developer creates their own named clone and gets their own port. The clones are fully isolated — one developer's migrations don't affect anyone else's clone.

What happens if I run out of ports? The default pool is 6000–6099, giving you 100 simultaneous clones. You can expand the range in the config. Realistically, clones should be destroyed after use, so you'd rarely approach that limit.

Is ZFS hard to manage? For this use case, no. You create the pool once during setup and DBLab manages everything inside it. You don't need to understand ZFS internals — just that it exists and powers the instant cloning.


The bottom line

The feature that made Neon feel magical — instant database branching with real production data — is available as open-source software on a €5/month Hetzner VPS. You just have to set it up yourself.

For me, that trade-off was worth it the month I saved €55. Every month since has been a bonus.

If you're running into the same Neon billing curve and want to try this, check out the DBLab documentation to get started. Drop me a message if you get stuck — I've hit every gotcha so you don't have to.

Thanks, Matija

📄View markdown version
0

Frequently Asked Questions

Comments

Leave a Comment

Your email will not be published

Stay updated! Get our weekly digest with the latest learnings on NextJS, React, AI, and web development tips delivered straight to your inbox.

10-2000 characters

• Comments are automatically approved and will appear immediately

• Your name and email will be saved for future comments

• Be respectful and constructive in your feedback

• No spam, self-promotion, or off-topic content

No comments yet

Be the first to share your thoughts on this post!

Matija Žiberna
Matija Žiberna
Full-stack developer, co-founder

I'm Matija Žiberna, a self-taught full-stack developer and co-founder passionate about building products, writing clean code, and figuring out how to turn ideas into businesses. I write about web development with Next.js, lessons from entrepreneurship, and the journey of learning by doing. My goal is to provide value through code—whether it's through tools, content, or real-world software.

Table of Contents

  • I Was Paying €60/Month for a Dev Database. Here's the Open-Source Alternative I Found.
  • The €60 wake-up call
  • What I actually needed from Neon
  • Enter DBLab
  • The mental model that makes it click
  • The vocabulary of branching
  • What a real dev morning looks like
  • How connection strings work
  • Why this beats a shared staging database
  • The honest comparison: Neon vs. self-hosted DBLab
  • What it runs on
  • The setup at a glance
  • What I gave up (and what I didn't miss)
  • FAQ
  • The bottom line
On this page:
  • I Was Paying €60/Month for a Dev Database. Here's the Open-Source Alternative I Found.
  • The €60 wake-up call
  • What I actually needed from Neon
  • Enter DBLab
  • The mental model that makes it click