Open-source alternative to Heroku Postgres

Heroku Postgres can be replaced with PostgreSQL you run on Dokku or Coolify for single-server workloads, or on CloudNativePG or Patroni when you need high availability. The work moves backups, failover and upgrades to your team.

On this page

Is there an open-source alternative to Heroku Postgres you can run yourself?

Yes. PostgreSQL is open source under the PostgreSQL License, a permissive license similar to the BSD and MIT licenses, and you can run it on your own servers through the official Dokku Postgres plugin or through the managed databases in Coolify. If a renewal, a plan change or a data residency requirement is prompting the Heroku Postgres review, the database itself is not the obstacle. The decisions that matter are where the database runs, who restores it, and how much downtime the business accepts when something fails. The trade-off is that backups, failover and upgrades move from Heroku to your team. Heroku Postgres plans carry those duties in the subscription, while a self-hosted database makes them your job. The Dokku postgres plugin can run scheduled backups to S3-compatible storage, and Coolify can run scheduled PostgreSQL backups with retention rules, but neither makes a single database server highly available. Confirm your recovery time and recovery point targets before choosing a design.

The right option depends on whether one server is enough. A single Dokku or Coolify host with a tested backup and restore procedure suits many internal and small customer-facing workloads. When downtime on a primary failure is not acceptable, you need streaming replication with a failover tool such as Patroni or an operator such as CloudNativePG, because PostgreSQL does not detect a primary failure or promote a standby on its own. Ask your team to confirm which PostgreSQL major version it will run, since the PostgreSQL versioning policy sets end-of-support dates for each release and version 14 reaches end of support in November 2026.

Which Heroku Postgres capabilities map to which PostgreSQL options

This table maps Heroku Postgres capabilities to the Dokku plugin, Coolify databases, CloudNativePG, Patroni, PgBouncer and PostgreSQL's built-in tools. Read the coverage column first, since several options cover a capability only partly. Most gaps sit in point-in-time recovery, automatic failover and upgrade planning, which you must own.

CapabilityDokku postgres pluginCoolify databasesCloudNativePG or Patroni with PostgreSQL tools
Provisioning and DATABASE_URL injectionCreates a Postgres service and links it to an app, setting DATABASE_URL, on a single Dokku serverCreates a PostgreSQL resource from the dashboard and exposes connection details for environment variablesCreates clusters through Kubernetes manifests or Patroni configuration, so you wire the connection string into app config yourself
Scheduled backupsOne-off or scheduled backups to S3-compatible storage through the pluginCron-scheduled pg_dump custom format backups, uploadable to S3-compatible storage, with retention by count, days or sizeDepends on the chosen backup tool; PostgreSQL provides the base archiving mechanisms you configure
Point-in-time recoveryGap: the plugin's documented backups are dump-based, so recovery is to the dump time, not to an arbitrary momentGap: pg_dump backups restore to the dump time and do not provide point-in-time recoveryAvailable through continuous WAL archiving and base backups, which you must set up, test and monitor
Read replicasNot a default plugin feature on a single host; confirm in the plugin README before planningNot a documented one-click feature; confirm current database options before relying on itHot standby servers serve read-only queries; the operator or Patroni configures and routes them
High availability and failoverNot provided; a single server is a single point of failureNot provided as an automatic failover feature; confirm with Coolify before relying on itPostgreSQL does not detect a primary failure or promote a standby by itself, so Patroni or CloudNativePG must be added
Connection poolingNot part of the plugin; confirm whether you add PgBouncer alongside the serviceNot a documented built-in; confirm before planning pool sizingPgBouncer is a separate project you deploy and configure in front of the database
Authentication (SCRAM, certificate, LDAP, OAuth)Set through PostgreSQL configuration; confirm how the plugin exposes pg_hba settingsSet through PostgreSQL configuration; confirm which methods the managed container exposesFull control in pg_hba.conf, including SCRAM, certificate, LDAP, GSSAPI and OAuth 2.0 in PostgreSQL 18
Major version upgradesPlugin image version is set by the plugin; plan dump and restore or pg_upgrade yourselfPlan dump and restore into a new resource, or pg_upgrade, as an operator taskLogical replication allows major upgrades with several seconds of downtime, but you build and test the cutover
Minor version patchingOperator replaces the image or executables and restarts; the storage format does not changeOperator updates the database image and restarts; confirm the update path with CoolifyRolling minor updates across a cluster are possible, but you own the sequence and rollback

Which self-hosted PostgreSQL option fits your team

Each option runs PostgreSQL on infrastructure you control, but they differ in who operates the database, how backups are scheduled and whether the database survives a host failure. Start with how many servers you run and whether you already operate Kubernetes, then check the backup and failover tasks each option leaves with your team.

Dokku postgres plugin

The official dokku-postgres plugin creates a PostgreSQL service on the same host as your Dokku apps and sets DATABASE_URL when you link it. The plugin's README lists PostgreSQL 18.6 as the default version, and it runs one-off or scheduled backups to S3-compatible storage. This fits a single-server Heroku replacement with modest data volumes. Check that the host can absorb database load next to your apps, and that someone owns restore tests, since a single host is also a single point of failure.

Coolify managed databases

Coolify deploys PostgreSQL as a managed resource from its web dashboard, with scheduled backups that use the pg_dump custom format, optional upload to S3-compatible storage and retention by count, days or size. It suits teams that prefer a UI over shell commands and want backups configured without writing cron jobs. Confirm the limits for multi-server use with Coolify's current documentation before you place a primary database on a server other than the one hosting the app, because a database that is not highly available still fails with its host.

CloudNativePG operator

CloudNativePG is a Kubernetes operator that manages PostgreSQL clusters, including replicas, failover and backups through its own resource definitions. It fits teams that already run Kubernetes and need a standby that takes over automatically after a primary failure. The cost is platform work: someone must own the cluster, storage classes, backup object storage and upgrade windows. Ask whether your Kubernetes platform team can staff that before you choose it over a single-server plugin.

Patroni on virtual machines

Patroni is external failover tooling that runs beside PostgreSQL on virtual machines and manages leader election, promotion and replica configuration through a distributed configuration store. PostgreSQL itself does not detect a failed primary or promote a standby, so this layer is what makes automatic failover possible. It fits teams that run VMs rather than Kubernetes and accept the operational load of etcd or a similar store, load balancing and failover drills. Expect to build monitoring and runbooks for each failover path.

How failover works when PostgreSQL does not detect failure itself

A hot standby is a running PostgreSQL server that replays changes from the primary and can serve read-only queries, which is useful for reporting or read scaling. It is not a failover mechanism by itself. PostgreSQL documents both synchronous replication, where a commit waits until the standby confirms it, and asynchronous replication, where the primary does not wait. The choice is a trade-off you must make explicitly: synchronous mode narrows the window of lost transactions but adds latency to every write and can stall commits if the standby disappears, while asynchronous mode keeps writes fast but can lose the most recent committed transactions when the primary fails.

PostgreSQL does not detect that the primary has failed, and it does not promote a standby on its own. The PostgreSQL failover documentation says external software must handle that job. On a Dokku or Coolify host, that means adding a tool such as Patroni or running CloudNativePG on Kubernetes, configuring it with a distributed consensus store or the operator's own coordination, and deciding how clients find the new primary. Confirm with the chosen tool's documentation how it behaves during a network partition and which replication mode it sets by default.

Several failover responsibilities stay with your team whichever tool you pick. You must design fencing so the old primary cannot accept writes after promotion, and you must protect against split-brain, where two nodes both believe they are primary and accept divergent writes. You must also decide who is paged, what recovery point objective the business accepts, and how applications reconnect. Schedule failover drills in a staging copy at least periodically, and record the measured promotion time and any data loss, because an untested standby is an assumption rather than a recovery plan.

What changes on one server versus a high-availability cluster

A single-server setup runs PostgreSQL in a container on the same host as Dokku or Coolify. Dokku's dokku-postgres plugin and Coolify's one-click PostgreSQL both place the database on the host that runs your apps, so there are fewer components to install, watch and upgrade. The trade-off is that one host failure takes the database and the applications down together.

  • Fewer moving parts: One host, one container runtime and one reverse proxy carry the whole stack, so there is little replication or failover configuration to maintain.
  • Single failure domain: A disk, kernel or hardware fault on the host stops the database. Recovery depends on restoring the latest backup onto a replacement host.
  • Backups carry the recovery plan: Dokku's plugin can run scheduled backups to S3-compatible storage, and Coolify uses pg_dump with retention rules. Both are your recovery path, so test restores regularly.
  • Patching is a host task: Operating system updates and PostgreSQL minor releases usually mean a planned restart with downtime for every app on that host.
  • On-call stays small: Alerts cover one host's disk, memory, backup jobs and container health.

Before you commit, confirm the recovery time you can accept and whether the team can rebuild the host from backups within it.

What you take on for backups, failover and upgrades

Moving off Heroku Postgres moves backups, recovery and upgrades to your team. On a self-hosted Dokku or Coolify server, the database is a container you operate, so you own the schedule, the retention policy and proof that a restore works. The dokku-postgres plugin can run one-off or scheduled backups to S3-compatible storage, and Coolify runs scheduled PostgreSQL backups in pg_dump custom format with retention set by count, days or size. Before cutover, confirm the backup destination sits outside the database host, run a full restore into a scratch server, and time it against your recovery goal. A backup that has never been restored is not a recovery plan.

Point-in-time recovery needs more than nightly dumps. PostgreSQL's continuous archiving method ships write-ahead log segments alongside a base backup so you can replay to a chosen moment, and the PostgreSQL documentation covers how to set this up. Coolify's own guide for teams coming from managed platforms makes the same point in a narrower form: a rollback can redeploy an application image but does not restore databases or persistent files. Ask your team to name who runs restores, where the archive lives, and how the archive is monitored for gaps.

Upgrades are the other recurring cost. Minor releases only replace executables and need a restart, while major upgrades go through pg_dumpall with restore, pg_upgrade, or logical replication, which the PostgreSQL documentation says can cut downtime to several seconds. PostgreSQL 14 support ends on November 12, 2026, and PostgreSQL 18 is supported until November 14, 2030, so plan the move onto a supported major version before the 14 date. Choose the upgrade method per database during a rehearsal on a copy of production data, and budget engineering time for it each year.

How to move Heroku Postgres data to your own PostgreSQL

This sequence moves a Heroku Postgres database to PostgreSQL you run on Dokku or Coolify, with row counts checked, a rehearsed cutover and the Heroku backup kept as a fallback.

  1. Inventory the database and its dependencies

    The app owner lists the Heroku Postgres plan, the PostgreSQL major version, installed extensions, roles, and every config var that points at the database, including any read replicas or followers. Confirm the current major version with the Heroku CLI and note which features the application relies on, such as extensions, custom types or scheduled jobs that write to tables. The step is done when the team has a written list of extensions, connection consumers and the target PostgreSQL version. Check that the target major version is still within PostgreSQL's support window, which the versioning policy lists by version.

  2. Take a fresh export from Heroku

    Run pg:backups to capture a logical backup, then download it with the Heroku CLI. Where the database is large or you need only part of it, run pg_dump directly against the connection string instead, using the custom format so the restore can run selectively. Store the file outside the new environment and record its checksum. The step is done when the dump file opens with pg_restore --list and the checksum is recorded in the migration log. Check the Heroku export limits and URL expiry in your plan before you start, because download links expire.

  3. Provision PostgreSQL on Dokku or Coolify

    On Dokku, install the dokku-postgres plugin, create a service and link it to the app so DATABASE_URL is set. On Coolify, add a PostgreSQL resource to the same server or project and attach it to the application. Match the major version to the Heroku source, or move to a newer one only after testing, and set a strong password and restrict network access to the application. The step is done when the service is running, the application can connect, and the DATABASE_URL value is confirmed without being printed in shared logs.

  4. Restore the dump and verify row counts

    Restore the custom-format dump with pg_restore or the platform import tool, then compare row counts, sequence values, index definitions and extension versions between Heroku and the new server for every table the application uses. Run a sample of application queries against both. Coolify's import accepts custom archives, and the dokku-postgres plugin can import a dump with postgres:import. The step is done when counts match for each table, sequences are past their maximum values, and the team has signed off on a verification record.

  5. Rehearse the cutover in a staging copy

    Run the full sequence against a staging app and database: restore, point the staging app at the new DATABASE_URL, run the test suite and a timed deploy. Record the steps, the commands and any surprises, such as missing extensions or connection limits. Agree on who freezes writes, who flips the config var and who checks the application afterwards. The step is done when a rehearsal completes without manual fixes and the runbook has been reviewed by the people who will run the live cutover.

  6. Use logical replication when downtime must be short

    If a full export and restore would leave the application offline for longer than the business allows, set up logical replication from the Heroku database to the new PostgreSQL server, which PostgreSQL supports across major versions. Confirm that Heroku permits the replication setup on your plan, then let the new server catch up while the old one stays live. The cutover then needs only a short write freeze and a sequence sync, which PostgreSQL's upgrade documentation describes as several seconds of downtime for major upgrades. The step is done when lag is near zero and the team has tested the sequence sync in staging.

  7. Cut over and set DATABASE_URL

    Stop writes to Heroku, wait for the final changes to apply, sync sequences, update DATABASE_URL in the new application environment, and deploy or restart the app. Keep the Heroku database in read-only mode rather than deleting it. Watch error rates, connection counts and background jobs for the first hours. The step is done when the application serves traffic from the new database, scheduled jobs run against it, and no writes reach Heroku.

  8. Keep the Heroku backup and set your own backups

    Retain the Heroku backup and the final export until the team agrees the new database is stable. Coolify's guide for teams coming from managed platforms notes that a rollback can redeploy a retained application image but does not restore databases or persistent files, so a database rollback needs its own recovery plan. Schedule backups on the new server, send copies to S3-compatible storage, and test a restore. The step is done when a restore from your own backup has been tested and the team knows which system is authoritative.

Questions buyers ask before replacing Heroku Postgres

What does it cost to replace Heroku Postgres with self-hosted PostgreSQL?

The cost is the sum of components you pay for separately: the server or VM that runs the database, block storage for data and write-ahead logs, S3-compatible storage for backups, a second node if you want standby capacity, and the staff time to build, monitor and patch it. The server and storage costs recur monthly, while setup and migration are one-time. Costs rise with database size, write volume, retention period for backups and the number of environments you copy. To compare fairly, ask any vendor or partner for line items for each component, plus whether the quote covers the first year of backups and restore tests. The open-source PostgreSQL license itself carries no fee, since PostgreSQL is released under the PostgreSQL License.

How long does a Heroku Postgres migration take?

Duration depends on database size, how much downtime the application can tolerate, the number of apps sharing the database, and how many environments need copies. A small database with a maintenance window can be moved with a dump and restore, while a larger one usually needs a replication-based cutover. Logical replication works between PostgreSQL major versions, which can keep the downtime to several seconds during a major upgrade, according to the PostgreSQL upgrading documentation. Ask for a written scope that names the cutover method, the rehearsal count, the rollback point and the acceptance tests, because those items set the timeline more than the raw data volume does.

Can our team migrate Heroku Postgres without outside help?

Yes, if your team already runs PostgreSQL in production and has a tested restore procedure. The tools are open source: the dokku-postgres plugin exports and imports databases, and Coolify restores PostgreSQL dumps. The harder parts are sizing, replication setup, credential rotation and verifying that restored data matches the source. Teams without this experience usually spend more time on those steps than on the copy itself. A written scope with a partner can cover the runbook, the cutover rehearsal and a documented handover, while your engineers keep ownership afterward. Decide early which of these you can staff internally.

What skills and on-call time does self-hosted PostgreSQL need?

You need people who can operate a database, not only deploy one. The work includes:

  • Monitoring connections, replication lag, disk growth, vacuum activity and slow queries
  • Testing backups by restoring them on a schedule, because a backup you have not restored is unproven
  • Applying minor releases, which PostgreSQL publishes at least once every three months, and planning major upgrades before a version leaves support
  • Responding to incidents at night when a node fails or storage fills

Confirm who is on call for the database, how alerts reach them, and what the escalation path is before cutover. Heroku handled these tasks for you, so the on-call rota moves to your team.

How do we get high availability and automatic failover on self-hosted PostgreSQL?

PostgreSQL supports hot standby servers and both synchronous and asynchronous replication, but it does not detect a primary failure or promote a standby by itself. Automatic failover therefore needs an external tool such as Patroni, or an operator such as CloudNativePG on Kubernetes. Synchronous replication protects commits at the cost of latency, and asynchronous replication can lose the most recent transactions on failover. Ask your team or partner to state the recovery point and recovery time they can meet, which decides the replication mode, and to show a failover test in your environment. A single Dokku or Coolify server gives you backups and restarts but not a standby.

How do we handle PostgreSQL upgrades after go-live?

Minor releases never change the internal storage format, so they mean replacing executables and restarting the server. Major upgrades use pg_dumpall with a restore, pg_upgrade, or logical replication. PostgreSQL 18 pg_upgrade keeps planner statistics and adds parallel jobs, according to the PostgreSQL 18 release announcement. Support for each major version ends five years after release, and PostgreSQL 14 is supported until November 12, 2026, per the versioning policy, so plan your first major upgrade inside that window. Ask any partner for the upgrade method, the rollback plan and whether testing against a copy of production is included in scope.

What should a written scope for this migration include?

A useful scope names the databases and apps moving, the target versions, the topology (single node, standby, or operator-managed cluster), the backup destination and retention, the cutover method and maximum downtime, the rollback point, and the handover documents. It should also list restore tests, monitoring and alerting setup, credential rotation, and the support period after go-live. Fixed-scope engagements, which are the common format at DeployOpen, put these items in writing before work starts, so you can compare quotes on the same basis. DeployOpen does not publish a price list, and a quote follows from that written scope.

When keeping Heroku Postgres is the better choice

Keeping Heroku Postgres is the better choice for some teams, and the test is whether the work you would take on by self-hosting is work you can staff and audit. Managed backups, point-in-time recovery and, for regulated workloads, the Shield tier with its compliance scope, carry operating duties that a self-hosted database hands to you. Before comparing monthly figures, pull your current plan from the Heroku pricing page and list what it includes: backup retention, recovery options, network isolation and the attestations your auditors expect. Then ask the same questions of the replacement.

The first check is compliance scope. If your auditor expects evidence from the database provider for backup, encryption or access controls, a self-hosted PostgreSQL moves that evidence to your team. Confirm with your assessor which controls you can cover with a self-hosted cluster and which you would need to document from scratch, and do not assume that a Dokku or Coolify host inherits any certification. The second check is skills. Someone on your team must own WAL archiving, restore drills, minor-version patching and major upgrades, because the PostgreSQL upgrading documentation assumes an operator who runs those steps.

The third check is recovery objectives. Write down how much data loss and how much downtime the business accepts, then test whether your self-hosted design meets them, including a restore into a clean environment. If the answer is no and the gap cannot be closed within your budget, keeping Heroku Postgres is a reasonable decision, and you can still use the database alongside a self-hosted application layer through a dump and restore plan.

How DeployOpen scopes and delivers a PostgreSQL replacement

DeployOpen plans, implements, hardens, backs up, documents and supports self-hosted PostgreSQL inside your own infrastructure, whether that is one Dokku or Coolify server or a high-availability cluster. Engagements are fixed-scope, with scope, deliverables and timelines agreed in writing before work starts.

How we scope

  • Inventory every Heroku Postgres plan, extension, connection pattern and backup schedule the application relies on today.
  • Agree in writing whether the target is a single-server plugin, a Coolify-managed database or a replicated cluster.
  • Define who owns backups, failover testing, upgrades and monitoring after handover, with a quote that follows from this scope.

How we build

  • Install and configure PostgreSQL on your servers or cloud accounts, with the dokku-postgres plugin or Coolify databases as agreed.
  • Set up authentication, TLS, backups to S3-compatible storage and restore tests against the agreed retention rules.
  • Test cutover steps in a non-production environment, including logical replication or dump-and-restore timing for your data size.

How we hand over

  • Deliver runbooks for connection changes, backup restores, minor and major version upgrades, and failover decisions.
  • Document which controls, logs and evidence are produced, so your auditors can review them without guessing.
  • Walk your operations team through restore drills so the first real recovery is not the first time anyone has run one.

How we support

  • Offer ongoing support, upgrades and continuous testing as a retainer after the fixed-scope delivery ends.
  • Plan minor releases and major upgrades against the PostgreSQL support windows your team agrees to track.
  • Confirm with your team which on-call, monitoring and incident responsibilities sit with you and which sit with DeployOpen.

Sources and further reading

Talk to our team.

Tell us what you're working on, whether it's a deployment, an audit, a security test or a cyber range. You'll speak with an engineer who can help you scope it.

  • 30-minute call: free, with no obligation.
  • NDA on request: we can sign before you share details.
  • Clear next steps: a scope and plan after the call.