We run four SaaS products in production right now, all on Postgres, all self-hosted on a Proxmox box that lives in our office. The electricity bill last month was 22 EUR. The equivalent on a managed Postgres provider would be roughly 280 EUR per month for the same compute and storage shape. That gap is real, but it does not mean self-hosting Postgres is the right answer for everybody. Here is the cost breakdown we actually ran, the failure modes we have lived through, and the line we draw between owned and managed in 2026.
What we actually run
To make the numbers concrete: we run Postgres for Carriva (retirement-advisor SaaS), the lesson-planning monorepo (PrepareMesCours, DraftMyLesson, PrzygotujLekcje, with Creaclases coming online in pre-prod), draftedby.com analytics, and a few internal tools. Total active row count across all databases is in the low millions, with the largest single database around 6 GB of data on disk. Daily query volume is modest, peaks under 200 QPS.
The hardware is one Proxmox host with a 12-core CPU, 64 GB of ECC RAM, and NVMe storage. It hosts roughly 14 LXC containers and VMs at any given time, of which 3 are Postgres instances. We run Postgres in containers with explicit memory limits, separate data mountpoints, and a paranoid backup policy that pushes encrypted snapshots to a NAS over the LAN and to an off-site location daily.
The honest cost comparison
Here is the apples-to-apples number we ran in November 2025 when we re-evaluated whether to migrate to a managed provider:
For a 4 vCPU / 8 GB RAM / 100 GB SSD Postgres instance with daily backups and read replicas optional:
- Managed provider A (the big cloud one): around 220 EUR per month per instance. Three instances would be around 660 EUR per month.
- Managed provider B (the developer-friendly one): around 180 EUR per month per instance.
- Self-hosted on our Proxmox box: amortized hardware cost (4-year depreciation on a 1,800 EUR build) plus electricity is roughly 60 EUR per month for the entire box, not per instance. We run 14 services on it. Postgres's share of that is maybe 15 EUR per month total across three instances.
The savings are not theoretical. Across 12 months they pay for the hardware twice over. But that math only works if we can reliably run Postgres ourselves. That is the part most "self-host everything" content skips.
The work that is not in the price tag
The cost difference exists because a managed provider takes away a real list of obligations:
- Daily backups, tested weekly. (Untested backups are vapor.)
- Point-in-time recovery (PITR) configuration with WAL archiving.
- Major version upgrades, including the dump-restore dance for breaking changes.
- Connection pooling (we use PgBouncer in transaction-pool mode).
- Disk space monitoring with alerts that actually fire.
- Replication setup if you ever need a hot standby.
- TLS certificate management for client connections.
- An incident plan for "the box is on fire at 3am, what do we do?"
We do all of that. None of it is hard. All of it takes time. If you bill yourself at 80 EUR per hour and you spend 4 hours per month on Postgres ops, that is 320 EUR per month in opportunity cost on top of the saved infrastructure spend.
For us the math still works because the time we spend on Postgres ops is also time we spend learning operational skills that compound across our solo developer Proxmox and Coolify homelab setup. The hours are not lost; they teach us the system.
The backup strategy that has saved us twice
We have lost data twice in the studio's history (both my fault). We have recovered both times. The strategy is the unglamorous part of self-hosting Postgres and the part that earns the savings.
Our flow:
pg_dump --format=customof every production database every night, run by a systemd timer inside the database container.- The dump is GPG-encrypted with a public key whose private half lives in a hardware token, then written to a directory that gets snapshotted by the host.
- The encrypted dump is rsynced to two NAS targets every night: one in the same building (fast restore) and one off-site (disaster recovery). Both go to specific, dated subfolders so we can roll back to any night for the last 30 days.
- A weekly canary restores the latest dump to a throwaway database and runs a query that asserts on a known invariant (row count for a stable table, or a specific record we know exists). If the canary fails, we get an alert.
Backups you have not restored are not backups. They are wishful thinking with a cron job.
The two times we needed this, we had a working database back in production within 35 minutes. That is the entire reason we are willing to operate Postgres ourselves.
When we still pay for managed
We do not self-host every database. The line is roughly:
- Customer-facing OLTP for our own products: self-hosted on Proxmox, because we know the workload and the failure modes.
- High-stakes external integrations (a database that, if it dies, takes down a partner's pipeline): we would pay for managed. We have not had this case yet.
- Anything that requires stringent compliance certifications we do not have: managed. The cost of a SOC 2 self-attest on a self-hosted Postgres is not worth it for a small studio. We pay the managed provider to inherit their certifications.
- Workloads with extreme spikes: managed Postgres can autoscale and our hardware cannot. We have not hit this yet, and the multi-tenant pattern we use (described in our day-one multi-tenant playbook) absorbs spikes within a single instance pretty gracefully.
The honest version: most small SaaS workloads do not need autoscaling Postgres. They need reliable Postgres. The mistake we see new founders make is paying 200 EUR per month for a managed Postgres at month one because someone on Twitter said "never run your own database". That is also wishful thinking with a credit card.
Postgres-specific gotchas in 2026
Three things bite us regularly enough to mention:
Connection limits and pooling
Postgres handles maybe 100 concurrent connections well. Beyond that, you need a pooler. We use PgBouncer in transaction mode in front of every production database. Most ORMs are fine with this if you remember to disable prepared statements at the app layer. We forgot once. The error messages were unhelpful. We never forgot again.
pg_dump is not a real backup strategy on its own
It is a logical dump. It is great. It is not point-in-time recovery. If you need PITR you need WAL archiving. We use a small wal-g-based setup pushing WAL segments to S3-compatible storage on the NAS. It is not free to set up but it is free once it works.
Major version upgrades are still a chore
Postgres 18 came out and we are still on 16 in production. Upgrading requires downtime or a logical-replication dance. Managed providers click a button. We schedule it for a quiet weekend. This is part of the time cost of self-hosting Postgres in 2026 and pretending otherwise is dishonest.
The Alpine Docker trap (Prisma users beware)
A specific footgun for the Next.js + Prisma crowd: if you build your app on an Alpine-based Docker image, Prisma needs linux-musl in its binaryTargets AND you need to install openssl in the runner stage. Forget either and you get cryptic runtime errors that look like the database is unreachable when it is not.
We learned this the hard way at 11pm during a deploy that we thought was a dry run. The fix is one line in schema.prisma and one line in the Dockerfile. We documented it in our internal cheat sheet so the next time we forget, we remember in 30 seconds.
The two-locations-for-every-backup rule
A pattern we standardized after one particularly bad afternoon: every database dump lands in two places. The first location is where the cron pushes its raw output (we use /share/Config/draftedby_db/ on the NAS, with timestamped files). The second is a human-organized layout (/share/Config/backup/<product>/<year-month>/) that we maintain manually for the dumps we want to keep long-term.
The cron output is the safety net (it is always there, generated automatically). The human-curated layout is the convenience surface (we know exactly where to find the December 2025 Carriva snapshot when somebody asks). Keeping these two layouts separate means we never accidentally delete an automated backup while reorganizing the curated archive. We have done that. Once. Never again.
If you self-host Postgres long enough, you will eventually develop your own two-locations rule. Plan for it on day one.
What we recommend for somebody starting fresh
If you are starting a SaaS in 2026 and you are deciding whether to self-host Postgres:
- Use managed in month one. Get the product to revenue. Do not let infrastructure spending be the reason you ship slowly.
- At month six, when you have real usage and a real bill, evaluate. If you are paying 200 EUR per month and your skills include "I can configure a Linux service", self-hosting Postgres is a reasonable next step.
- Self-host on owned or rented dedicated hardware, not on a generic VPS. The IO predictability matters. We use Proxmox on owned hardware. A Hetzner dedicated would also be fine.
- Have a backup script that you have actually restored from, before you do anything else.
- Plan for the day you migrate back to managed. That day might come if you grow into a different scale, and you do not want a hostage architecture. Keep your schema portable. Keep your application layer ignorant of where Postgres lives. We touched on this same principle in our piece on self-hosting analytics in 2026: own the data, but do not paint yourself into a corner.
What is next
Right now self-hosting Postgres is paying off for us. The day it stops paying off, we will move. The honest answer to "should I self-host Postgres?" is "do you want to learn the operational craft of running a database?" If yes, the savings are real and the skill is durable. If no, pay the 200 EUR per month and move on with your product. Both are legitimate. Pretending the first is "obviously cheaper" without counting the hours is the trap. We have walked through both sides of that trap and we still self-host. That is our answer. Yours might be different and that is fine.



