
Deploy Postgres Read Replicas
Send read traffic to streaming replicas on port 5433
Just deployed
/var/lib/postgresql/data
Just deployed
/var/lib/postgresql/data
Just deployed
Just deployed
/var/lib/postgresql/data
Deploy and Host self hosted Postgres Read Replicas (Highly Available PostgreSQL with Read Replicas) on Railway
This template gives you a three-node Patroni Postgres cluster with a router that splits traffic for you.
About Hosting Postgres Read Replicas open-source software on Railway (self hosted Postgres read replicas with Patroni template)
This template runs three Postgres 18.6 nodes under Patroni with etcd for leader election, plus a HAProxy router.
You own the data on your own volumes inside your Railway project. Railway handles scheduling, private networking, and the TCP proxy behind DATABASE_PUBLIC_URL.
Why Deploy Postgres Read Replicas, the AWS RDS read replicas alternative on Railway (Railway Free Trial)
AWS RDS read replicas are the managed option, but you pay per instance and per endpoint and get less say over tuning.
Railway is a singular platform to deploy your infrastructure stack. Railway will host your infrastructure so you don't have to deal with configuration, while allowing you to vertically and horizontally scale it.
By deploying Postgres Read Replicas on Railway, you are one step closer to supporting a complete full-stack application with minimal burden. Host your servers, databases, AI agents, and more on Railway.
Railway vs Other Hosting Providers and VPS for Postgres Read Replicas self hosting
Here is how the main options compare for running this three-node Patroni cluster.
| Provider | What You Get with Railway | What You Get with the Other Provider |
|---|---|---|
| DigitalOcean | The three nodes and HAProxy router deploy from one template with private networking. | Root access and fixed droplet pricing, but you wire up etcd, Patroni, and TLS yourself. |
| AWS | Ports 5432, 5433, and 8080 on one router without building VPC routing or an NLB. | Deep networking control, but read replicas are separate RDS endpoints and Patroni is manual. |
| Hetzner | Deploys, restarts, and private domains for the nodes handled for you. | Very low raw compute cost, but you own etcd quorum and replica lag monitoring. |
Pick the option that matches how much cluster plumbing you want to own.
Common Use Cases for hosted Postgres Read Replicas
-
Dashboards and reports on replicas: Point reporting dashboards at DATABASE_URL_READONLY so heavy aggregations run on the streaming replicas through port 5433. Numbers trail the primary by the replication lag.
-
Read-heavy APIs: Send GET endpoints to a read-only pool and keep writes on DATABASE_URL. Read traffic spreads across both replicas instead of loading the primary.
-
Analytics kept off the primary: Long scans run on a replica so the primary stays responsive. A replica may cancel a query if replay conflicts with it.
-
A read-only user for BI tools: Connect tools like Metabase with a SELECT-only role on port 5433. Writes from BI tools fail on a hot standby, which is a useful safety net.
-
pgvector similarity search on replicas: Run nearest-neighbor searches on the replicas, since pgvector data replicates like any other table. Embedding writes still go through the primary.
Dependencies for Postgres Read Replicas Docker hosted on Railway
This template runs as a small Patroni cluster, so you deploy several services that depend on each other.
Deployment Dependencies for Managed Postgres Read Replicas Service (PostgreSQL Cluster)
One click deploys pg-1, pg-2, pg-3 and the router; etcd runs inside each node and forms quorum. Your app uses DATABASE_URL for writes and DATABASE_URL_READONLY for reads.
Implementation Details for Postgres Read Replicas (Using Postgres HA official docker image)
The node service uses ghcr.io/onepush-dev/postgres-ha-node:18.6 and the router uses ghcr.io/onepush-dev/postgres-ha-router:18.6, both pinned by digest.
How does Postgres Read Replicas compare against other ways to add Postgres read replicas
Postgres HA vs AWS RDS read replicas (AWS RDS read replicas Alternative)
- Ops Surface: RDS handles replica creation, patching, and failover for you. Here you run three Patroni nodes and an HAProxy router yourself, so you own upgrades.
- Endpoints: RDS gives each replica its own endpoint. Here port 5433 spreads reads across both streaming replicas, and DATABASE_URL_READONLY points your app at it.
- Cost Shape: RDS bills per instance and storage. Here you pay Railway usage for three nodes plus the router, around $25-60/mo at light use.
Postgres HA vs a single Railway Postgres (Single Railway Postgres Alternative)
- Read Scaling: A single Railway Postgres has no streaming replicas, so every read and write hits one server. Postgres HA moves reporting queries to 5433 and keeps the primary free for writes.
- Failover: One node is one point of failure. Patroni promotes a replica when the primary goes away, and the router follows the health checks.
- Simplicity: If read load is small, a single Railway Postgres is simpler, and three nodes is more machinery than you need.
Postgres HA vs Neon read replicas (Neon Read Replicas Alternative)
- Storage Model: Neon separates compute from storage, so its replicas are serverless compute on shared storage. Postgres HA runs classic streaming replicas, each with its own copy of the data.
- Lag Behavior: Replication here is asynchronous by default, so a replica read right after a write may not see it yet. Neon has a different lag profile, so test your read-your-writes paths against whichever you pick.
Postgres HA vs PgBouncer alone (PgBouncer Alternative)
- Purpose: PgBouncer pools connections but adds no copies of your data. Postgres HA adds streaming replicas, so reads actually leave the primary.
- Failover: PgBouncer does not promote a new primary when one fails. Patroni does, and the router sends writes to whichever node is currently primary.
- Where PgBouncer Wins: If your only problem is too many connections and one healthy primary, PgBouncer alone is the smaller fix, and you can still run it in front of this cluster later.
How to use Postgres Read Replicas (the OSS highly available PostgreSQL)?
- Deploy the template and wait until the router's /status endpoint returns primary_up=1 and replicas_up=2 before you point anything at it.
- In your app service, keep DATABASE_URL for writes (router port 5432, primary) and add DATABASE_URL_READONLY for reads (router port 5433, replicas).
- Confirm which node you reached on each port. Run SELECT pg_is_in_recovery(); on 5432 it should return false, and on 5433 it should return true.
- Check replication lag on the primary with pg_stat_replication, since async replicas can trail a little behind your writes.
- Route read-only queries in your ORM to the read connection, and send anything that must see its own fresh write back to the primary.
psql "$DATABASE_URL" -c "SELECT pg_is_in_recovery();"
psql "$DATABASE_URL_READONLY" -c "SELECT pg_is_in_recovery();"
psql "$DATABASE_URL" -c "SELECT client_addr, state, replay_lag FROM pg_stat_replication;"
How to self host Postgres Read Replicas on other VPS Services (Postgres HA self hosting guide)
Self hosting means wiring up the three Patroni nodes, the etcd layer, and the HAProxy router yourself. These steps assume Docker and Docker Compose on each host.
Clone the Repository
Pull the template source onto a machine that can reach your other nodes over a private network.
git clone https://github.com/onepush-dev/postgres-ha.git
cd postgres-ha
Install Dependencies
Install Docker Engine and the Compose plugin on every VPS that runs a Postgres node or the router.
Configure Environment Variables
Set the same superuser, replication, and REST API credentials on all three nodes so they can form the cluster.
Start the Postgres Read Replicas Application
Bring up etcd and Patroni on each node, then start the router once a primary and two replicas report healthy.
docker compose up -d
curl http://your-domain:8080/status
A healthy cluster returns primary_up=1 and replicas_up=2. Railway handles the private networking, shared secrets, and restarts for you.
Official Pricing of Postgres Read Replicas (Postgres HA pricing)
Postgres HA itself is free and open source, so there is no license fee to pay.
Postgres Read Replicas cloud vs self hosted comparison (Pricing, features, costs, and more)
Self hosting means you own the Patroni, etcd, and HAProxy plumbing and the bill for every node. The comparison below sets Railway against a self hosted VPS.
Monthly cost of self hosting Postgres Read Replicas on Railway
On Railway the three Postgres nodes plus the router run at roughly $25-60 per month at light use, rising as data and RAM grow.
System Requirements for Hosting Postgres Read Replicas on a VPS
Plan for three separate machines so one host failure cannot take out the primary and both replicas. Keep ports 5432, 5433, and 8080 reachable from your app only.
Frequently Asked Questions (FAQs)
How stale can a replica read be?
Replication is asynchronous by default, so a replica can trail the primary by milliseconds under light load and much longer when busy.
What happens to the read port during a failover?
Patroni promotes a healthy replica, and HAProxy follows the REST health checks to route to the new primary and the surviving replica.
Can I write to port 5433?
No. Send writes to port 5432 or DATABASE_URL.
Why was my long query cancelled on a replica?
Replay cancels a query when it must remove rows the query still needs, such as after a vacuum on the primary.
How do I read my own writes?
Route reads that must see a fresh write to the primary through DATABASE_URL, since replicas can lag.
Can I add more replicas?
Yes, but this template ships with two, and the router and health checks assume that layout.
Template Content
