Isometric illustration comparing a managed cloud PostgreSQL database with a self-hosted database on your own server

Managed PostgreSQL vs self-hosted comes down to who owns backups, restores, failover, upgrades and the 3 AM pages. A managed database from Heroku, Render or Fly.io costs more per gigabyte of RAM, but the provider runs all of that for you. A self-hosted PostgreSQL on a VM costs a few euros a month in hardware and several hours a month of skilled work, plus the risk that a backup nobody tested doesn’t restore. For most Rails teams without a dedicated ops person, managed is the right default. This guide compares what each option actually includes, shows real prices, and explains when self-hosting is worth it and how to do it safely.


TL;DR

  • Managed PostgreSQL buys you automated backups, failover (on HA plans), patching and monitoring. Self-hosting means building, testing and operating all of that yourself.
  • Entry-level managed plans are cheap ($5–6/month on Heroku or Render), but production-grade plans with HA start at $38/month (Fly.io Managed Postgres) and $200/month (Heroku Premium-0).
  • A VM that can run PostgreSQL costs roughly €5–10/month in 2026, but the real cost is 1–2 days of setup and a few hours a month of maintenance.
  • Self-host only if someone on the team has PostgreSQL operations experience, you’ve automated backups with point-in-time recovery, and you test restores regularly.
  • Whichever you choose, the Rails side is identical: DATABASE_URL, a sensible pool size and timeouts.

Table of Contents

What is the difference between managed and self-hosted PostgreSQL?

With managed PostgreSQL, a provider runs the database server, operating system, backups, replication and upgrades, and gives you a connection URL. With self-hosted PostgreSQL, you run it on a server you control, and every one of those jobs is yours.

Managed vs self-hosted PostgreSQL: who runs what, and how much time it takes

The database engine is the same PostgreSQL either way, and Rails doesn’t care which one you pick. What differs is the work around it:

Responsibility Managed Self-hosted
Install and configure PostgreSQL Provider You
OS security patches Provider You
PostgreSQL minor updates Provider (scheduled) You
Major version upgrades Provider tooling, you schedule You (pg_upgrade or dump/restore)
Daily backups Provider You (pgBackRest, WAL-G, pg_dump)
Point-in-time recovery Most production plans You (WAL archiving)
Restore testing Provider tests the mechanism; you test your data You
High availability and failover HA plans only You (Patroni, repmgr)
Monitoring and alerts Dashboards included You (postgres_exporter, alerts)
Connection pooling Often included (PgBouncer) You
Query performance, indexes, schema You You

The last row is the one people forget. A managed database doesn’t fix slow queries or missing indexes. The Rails performance optimization guide applies equally to both.

What does a managed PostgreSQL plan actually include?

Managed plans vary widely, and the entry tier is usually missing the features you’re paying a managed provider for. Read the plan details before assuming you have high availability or point-in-time recovery.

Feature Heroku Essential Heroku Standard / Premium Render Basic Fly.io Managed Postgres
Dedicated resources No (shared) Yes Shared CPU fraction Shared-2x and up
Automated backups Yes Yes Yes Yes
Point-in-time recovery No Yes Paid plans Not documented
High availability No Premium and above Higher tiers Included on all plans
Connection pooling No Server-side pooling on larger plans PgBouncer on paid plans PgBouncer included
Storage 1–32 GB 64 GB+ Per GB ($0.30) Per GB ($0.28)

Plan features from each provider’s documentation in October 2026. Fly.io lists security patches and version upgrades as “not there yet” for Managed Postgres.

Two consequences:

  • “Managed” doesn’t automatically mean “highly available”. On Heroku, HA starts at Premium-0 ($200/month). Below that, a hardware failure means downtime while the provider recovers the database.
  • Read the backup retention and recovery options. Daily snapshots alone mean you can lose up to a day of data. Point-in-time recovery shrinks that to minutes.

Pros and cons of each option

Managed PostgreSQL

  • ✅ Backups, patches and monitoring work from day one, with no setup.
  • ✅ Failover and point-in-time recovery on the right plan, operated by people who do it every day.
  • ✅ No PostgreSQL operations knowledge needed on the team.
  • ❌ Several times more expensive per GB of RAM than a VM.
  • ❌ Plan tiers force jumps: you pay for the next tier’s storage to get its connection limit, or the other way round.
  • ❌ Limited superuser access and extensions, and sometimes slow major-version upgrades.
  • ❌ Data lives where the provider runs, which matters for some data-residency requirements.

Self-hosted PostgreSQL

  • ✅ Cheapest per GB of RAM and per GB of disk, by a wide margin.
  • ✅ Full control over configuration, extensions, version and location.
  • ✅ No connection-limit tiers: max_connections is whatever the hardware supports.
  • ❌ Backups, restores, failover, patching and monitoring are your job, forever.
  • ❌ Mistakes are silent until they’re catastrophic. An unmonitored full disk or a broken WAL archive is found during the incident.
  • ❌ The person who knows how it works becomes a single point of failure too.

How much does managed vs self-hosted PostgreSQL cost?

At list prices, a production-ready managed database for a small Rails app costs $19–75/month, and an HA plan from $38/month (Fly.io) to $200/month (Heroku). A self-hosted VM costs about €5–10/month, but adds 1–2 days of setup and a few hours of work every month.

Option Plan RAM Price/month HA Notes
Heroku Essential-0 Shared $5 No 1 GB storage, limited connections
Heroku Standard-0 4 GB $50 No 64 GB storage, 200 connections
Heroku Premium-0 4 GB $200 Yes HA and longer rollback
Render Basic-256mb 256 MB $6 No 1 GB storage included, then $0.30/GB
Render Basic-1gb 1 GB $19 No 10 GB storage included
Fly.io MPG Basic 1 GB $38 + storage Yes Shared-2x CPU, $0.28/GB storage
Fly.io MPG Starter 2 GB $72 + storage Yes  
Self-hosted Budget EU VM, 2–4 vCPU, 4–8 GB 4–8 GB ~€5–10 No (one VM) Plus backup storage (a few € for S3-compatible)
Self-hosted Two VMs + replication 4–8 GB each ~€10–20 Manual or Patroni Plus your time to build failover

Managed prices from Heroku Elements, Render and Fly.io pricing pages, October 2026. VM prices are a range because European budget providers changed their prices several times in 2026; check current pricing.

The hardware comparison is lopsided: the same euros buy roughly 4–8× more RAM on a VM. Engineering time evens it out. If your time is worth €50/hour and self-hosting costs three hours a month, that’s €150/month, more than most managed plans in the table, before counting the risk.

That arithmetic is the same one behind the true cost of Ruby hosting and startup hosting costs: the database is usually the line item that jumps the most between “MVP” and “production”.

How Heroku, Render, Fly.io, Upsun and Enkihost run PostgreSQL

Each platform offers PostgreSQL as an add-on or service that injects DATABASE_URL, but they put the line between “managed” and “your problem” in different places.

Platform Offering Backups and recovery HA Upgrades Pooling
Heroku Heroku Postgres add-on Continuous protection and rollback on Standard+; pg:backups on all Premium+ pg:upgrade tooling Server-side pooling on larger plans; PgBouncer buildpack
Render Render Postgres Daily backups; point-in-time recovery on paid plans Higher tiers Upgrades in place, scheduled by you Integrated PgBouncer on paid plans
Fly.io Managed Postgres (MPG) Automatic backups and recovery Included, automatic failover Not yet available PgBouncer on every cluster
Fly.io Unmanaged Postgres on Machines You (it’s an app you run) You You You
Upsun postgresql service Manual and scheduled backups of the environment Not by default Change the service version in config Not part of the standard service
Enkihost PostgreSQL included: 512 MB RAM / 5 GB disk on Ignite, five 2 GB databases on Blaze Not documented Blaze plan lists high availability Not documented Not documented

The Fly.io split is instructive: it has both. Fly’s older Postgres offering was explicitly “not managed”, an app running on Machines that you operate yourself, and Managed Postgres was introduced for teams who don’t want that job. The cost difference between the two is the cost of operations.

Enkihost’s included PostgreSQL injects DATABASE_URL, so Rails connects to it the same way as on any platform above, with no change to database.yml.

If you self-host: the minimum production setup

If you self-host, the minimum is: PostgreSQL from the official repository, no public access, TLS, continuous WAL archiving with point-in-time recovery to object storage, monitoring with alerts, and a monthly restore test. Anything less is a database waiting for an incident.

1. Install from the PostgreSQL project’s repository so you get current minor releases:

sudo apt install -y postgresql-common
sudo /usr/share/postgresql-common/pgdg/apt.postgresql.org.sh -y
sudo apt install -y postgresql-17 pgbackrest

2. Lock down access. Listen only on the private network, require TLS and SCRAM passwords:

# /etc/postgresql/17/main/postgresql.conf
listen_addresses = 'localhost,10.0.0.5'
ssl = on
password_encryption = scram-sha-256

# Rough starting values for a dedicated 8 GB server
shared_buffers = 2GB
effective_cache_size = 6GB
work_mem = 16MB
maintenance_work_mem = 512MB
max_connections = 100

# WAL archiving for point-in-time recovery
wal_level = replica
archive_mode = on
archive_command = 'pgbackrest --stanza=main archive-push %p'
# /etc/postgresql/17/main/pg_hba.conf
# TYPE    DATABASE        USER   ADDRESS        METHOD
local     all             postgres               peer
hostssl   app_production  app    10.0.0.0/24    scram-sha-256

3. Back up continuously with pgBackRest to an S3-compatible bucket, encrypted:

; /etc/pgbackrest/pgbackrest.conf
[global]
repo1-type=s3
repo1-s3-bucket=myapp-pg-backups
repo1-s3-endpoint=s3.eu-central-1.amazonaws.com
repo1-s3-region=eu-central-1
repo1-s3-key=AKIA_REPLACE_ME
repo1-s3-key-secret=REPLACE_ME
repo1-path=/pgbackrest
repo1-retention-full=2
repo1-cipher-type=aes-256-cbc
repo1-cipher-pass=REPLACE_WITH_LONG_RANDOM_PASSPHRASE
start-fast=y
compress-type=zst

[main]
pg1-path=/var/lib/postgresql/17/main
sudo -u postgres pgbackrest --stanza=main stanza-create
sudo -u postgres pgbackrest --stanza=main check
sudo -u postgres pgbackrest --stanza=main --type=full backup
# /etc/cron.d/pgbackrest
30 2 * * 0   postgres  pgbackrest --stanza=main --type=full backup
30 2 * * 1-6 postgres  pgbackrest --stanza=main --type=diff backup

4. Test restores every month on a separate machine, to a point in time:

sudo systemctl stop postgresql
sudo -u postgres pgbackrest --stanza=main --delta \
  --type=time "--target=2026-10-22 09:00:00+03" --target-action=promote restore
sudo systemctl start postgresql
sudo -u postgres psql -d app_production -c "SELECT max(created_at) FROM orders;"

5. Monitor and alert at least on: disk usage above 80%, replication or archive lag, failed backups (pgbackrest info), connection count near max_connections, and long-running transactions.

Running PostgreSQL as a Kamal accessory works the same way, but the data volume and backups are still yours. Kamal won’t replicate or back it up for you. Connection sizing for either setup is covered in the connection pool guide.

Should you use managed or self-hosted PostgreSQL?

Choose by your team’s operations experience first and by budget second.

Situation Recommendation
Solo developer or small team, no ops experience Managed. The savings from self-hosting are smaller than the cost of one bad incident.
MVP or side project Entry-level managed plan. Upgrade the plan before launch, not after the first outage.
Production SaaS with paying customers Managed with daily backups and point-in-time recovery. HA once downtime costs more than the plan.
Team with a PostgreSQL-savvy engineer, cost-sensitive, large data Self-hosted on dedicated hardware with pgBackRest, monitoring and documented runbooks.
Strict data residency or custom extensions Self-hosted, or a managed provider in the required region that supports the extension.
Many small apps, each with a small database One self-hosted or managed server with a database per app, if isolation requirements allow it.

Author Perspective: the backup you never restored

I’ve self-hosted PostgreSQL for years and I’d still tell most teams to use a managed database. Running PostgreSQL isn’t hard. The hard part is the discipline: a restore test every month, alerts somebody actually reads, a runbook for the full-disk night, and upgrades done before the version goes out of support. The worst database incident I ever saw wasn’t a crash. It was a team discovering, mid-crisis, that their nightly pg_dump had been producing empty files for six weeks. If you self-host, put “restore last night’s backup to a scratch server” on the calendar and treat it as seriously as a deploy. If that sounds like a chore nobody will do, that’s your answer: go managed.

PostgreSQL on Enkihost

For Rails apps on Enkihost, PostgreSQL is included in the plan, so the database comes up next to your app without you building the server yourself:

Enkihost

  • PostgreSQL add-on that injects DATABASE_URL, so Rails connects with the standard database.yml, and Solid Queue, Solid Cache and Solid Cable can share it.
  • Redis add-on that injects REDIS_URL for apps that want to keep caching or Sidekiq off the database.
  • Per-app resource isolation, so your app’s queries aren’t competing with someone else’s traffic on the app side.
  • Zero-downtime deploys that work with the expand-and-contract migration patterns your database changes need.

Rails and Sinatra apps run on Ignite (9 EUR per month after a 14-day free trial, with PostgreSQL and Redis included) or Blaze (29 EUR per month, with high availability and autoscaling). The free Spark plan is for Jekyll sites. See enkihost.com.

FAQ

Is managed PostgreSQL worth the cost?

For most small and medium Rails teams, yes. The extra monthly cost is usually less than the engineering time needed to build and maintain reliable backups, monitoring, patching and failover yourself, and much less than the cost of losing data. Self-hosting pays off mainly for teams with PostgreSQL operations experience and large databases.

Can I run PostgreSQL in Docker in production?

Yes, many teams run PostgreSQL in a container, including as a Kamal accessory, with the data directory on a persistent volume. The container changes nothing about the operational work: you still need WAL archiving, tested restores, monitoring, upgrades and a plan for host failure.

How often should I back up a production PostgreSQL database?

Continuously, if you can. Archive the write-ahead log for point-in-time recovery, combined with a full backup weekly and differential backups daily. That limits data loss to minutes. A nightly pg_dump alone can lose up to a day of data and takes longer to restore for large databases.

Does managed PostgreSQL include high availability?

Not always. Entry-level and many mid-tier plans run a single instance without automatic failover. On Heroku, high availability starts with the Premium tier, while Fly.io Managed Postgres includes it on every plan. Check the plan details for failover before relying on it.

Is it hard to migrate from managed to self-hosted PostgreSQL later?

It is straightforward for small databases: dump with pg_dump, restore with pg_restore, and change DATABASE_URL during a short maintenance window. Large databases need logical replication to keep downtime short. Rails itself needs no changes beyond the connection URL.

Sources