[{"data":1,"prerenderedAt":163},["ShallowReactive",2],{"seo-verification":3,"blog-postgresql-self-hosted-vs-rds-en":6},{"google":4,"bing":5},"EycwPY2XMyTkVzas3n1ygeNJFGAH513qrMjfDljzsMQ","",{"id":7,"slug":8,"title":9,"excerpt":10,"readTime":11,"views":12,"isPinned":13,"publishedAt":14,"category":15,"categories":21,"featuredImage":23,"bgImage":24,"posterImage":25,"relatedSolution":23,"intro":26,"sections":27,"ctaTitle":124,"ctaBody":125,"ctaButton":126,"ctaUrl":127,"relatedPosts":128},239,"postgresql-self-hosted-vs-rds","Self-Hosted PostgreSQL vs Amazon RDS: ROI Comparison","Real cost of PostgreSQL on a VPS vs Amazon RDS in 2026: figures, configuration, troubleshooting and migration guide.",9,0,false,"2026-08-09T00:00:00+00:00",{"id":16,"name":17,"slug":18,"color":19,"icon":20},6,"Databases","bases-de-donnees","bg-teal-500\u002F10 text-teal-400","database",[22],{"id":16,"name":17,"slug":18,"color":19,"icon":20},null,"\u002Fblog\u002Fcovers\u002Fbg.svg","\u002Fblog\u002Fcovers\u002Fpostgresql-self-hosted-vs-rds-poster.svg","The Amazon RDS bill grows as the database grows — storage, IOPS, connections, Multi-AZ: each parameter adds a line item. Self-hosted PostgreSQL on a dedicated VPS reverses the equation: fixed, predictable cost, unrestricted extensions, full root access. This guide compares both models with real numbers, covers the installation steps, and addresses the most common objection: who manages the server.",[28,32,43,79,82,107,110,113,121],{"type":29,"title":30,"body":31},"h2","Why re-evaluate RDS in 2026","Amazon RDS for PostgreSQL is a solid managed database, but its billing model is designed so the invoice scales non-linearly with growth. Each component is billed separately: instance compute, gp3 storage per GB, provisioned IOPS, Multi-AZ replication nodes, backups beyond the included window, outbound data transfers. A `db.r6g.4xlarge` instance in Multi-AZ with 500 GB of gp3 storage exceeds $3,000\u002Fmonth on us-east-1 on-demand pricing. The same workload on a three-node Hetzner Cloud cluster runs around $835\u002Fmonth — a saving of $2,315\u002Fmonth, roughly $27,800 over twelve months (source: \u003Ca href=\"https:\u002F\u002Fselfhost.dev\u002Fblog\u002Faws-rds-vs-hetzner-cloud-cost\u002F\">selfhost.dev, May 2026\u003C\u002Fa>, HN item #48816129). This figure covers a complete high-availability cluster. For a development database, a staging environment, or a business workload without replication, a single node is enough for a fraction of that cost. The pricing landscape also shifted in 2026: Hetzner revised its rates in April then June 2026, and OVHcloud updated its VPS pricing in April 2026. These increases change the absolute numbers, not the logic — self-hosting remains structurally cheaper once the database exceeds a few dozen GB and the traffic demands a non-burstable instance. The question is no longer whether self-hosting costs less — the numbers confirm it — but whether the operational overhead is worth the savings.",{"type":33,"title":34,"items":35},"ul","What you gain by switching to a VPS",[36,37,38,39,40,41,42],"**Fixed, predictable cost** — no billing per GB, extra IOPS, or simultaneous connections; you size your VPS once and the price does not change with query volume.","**Unrestricted extensions** — PostGIS, TimescaleDB, pg_partman, pgvector, citus: no arbitrary restrictions, unlike RDS where the list is closed and unsupported extensions are absent.","**Root access and fine-grained configuration** — `postgresql.conf`, `pg_hba.conf`, `huge_pages`, `wal_level`, connection poolers: adjust every parameter without going through a cloud console and without restrictions on system tools.","**Version control** — you decide when to move from PostgreSQL 16 to 17, without imposed maintenance windows or forced deprecation by the vendor.","**Data within your perimeter** — choose the datacenter, encrypt volumes according to your internal policy, no cross-region data transfer charges on every analytical read.","**Full portability** — `pg_dump` or logical replication moves your data to any other host without vendor friction and without egress fees.","**Administration option available** — if operational overhead remains the main objection, the VPS administration option covers routine tasks (updates, monitoring, backups); you keep control, not the workload.",{"type":44,"title":45,"headers":46,"rows":50},"comparison","PostgreSQL on VPS vs Amazon RDS: comparison table",[47,48,49],"Criterion","PostgreSQL on VPS","Amazon RDS for PostgreSQL",[51,55,59,63,67,71,75],[52,53,54],"Monthly cost (standard workload)","Fixed — proportional to the chosen server","Variable — compute + storage + IOPS + Multi-AZ + network egress",[56,57,58],"High-availability example (3 nodes \u002F Multi-AZ)","~$835\u002Fmonth (Hetzner CCX53 cluster, May 2026)","~$3,150\u002Fmonth (db.r6g.4xlarge Multi-AZ, us-east-1)",[60,61,62],"PostgreSQL extensions","All, including PostGIS, pgvector, TimescaleDB, citus","Restricted list; unsupported extensions absent",[64,65,66],"Root \u002F OS access","Yes — OS choice, Docker, cron, kernel tuning, pgBouncer","No — AWS API only, restricted parameters",[68,69,70],"Version upgrades","At your own pace, without imposed maintenance windows","Scheduled or forced by AWS at deprecation",[72,73,74],"Operational overhead","Backups, updates, monitoring to manage","Automated by AWS: backups, patches, failover",[76,77,78],"Portability","Full — `pg_dump` or logical replication, no egress fee","Tied to AWS ecosystem, data export is paid",{"type":29,"title":80,"body":81},"Prerequisites before migrating","A VPS with 4 GB RAM and 2 vCPU is sufficient for most web application databases under 50 GB with moderate traffic and fewer than 50 concurrent connections. For a more demanding database, an analytical schema with many joins, or a service exposed to traffic spikes, plan for at least 8 GB RAM. SSD NVMe storage is essential: PostgreSQL's random access patterns on a rotational disk or entry-level SATA SSD significantly degrade performance, particularly on cache warm-up after a restart. Root access is required — standard on any cloud VPS. On the network side, you will need a fixed IPv4 address or an internal domain name to point your application connections to. Finally, plan a migration window where both databases run in parallel: the application points to RDS while you populate the VPS, verify consistency, then switch the connection variable. Duration depends on volume: a 5 GB dump restored in parallel takes minutes; 200 GB may take several dozen.",{"type":83,"title":84,"steps":85},"steps","Install and configure PostgreSQL on a VPS",[86,89,92,95,98,101,104],{"title":87,"body":88},"Install PostgreSQL from the official PGDG repository","On Ubuntu 24.04 or Debian 12, add the PostgreSQL Global Development Group repository to get the current version rather than the distribution-packaged one: `curl -fsSL https:\u002F\u002Fwww.postgresql.org\u002Fmedia\u002Fkeys\u002FACCC4CF8.asc | sudo gpg --dearmor -o \u002Fetc\u002Fapt\u002Ftrusted.gpg.d\u002Fpostgresql.gpg` then `echo \"deb http:\u002F\u002Fapt.postgresql.org\u002Fpub\u002Frepos\u002Fapt $(lsb_release -cs)-pgdg main\" | sudo tee \u002Fetc\u002Fapt\u002Fsources.list.d\u002Fpgdg.list`. Then: `sudo apt update && sudo apt install -y postgresql-17`.",{"title":90,"body":91},"Create a dedicated user and database","Connect as `postgres`: `sudo -u postgres psql`. Then create a dedicated application user and isolated database: `CREATE USER myapp WITH PASSWORD 'strong-password';` followed by `CREATE DATABASE myapp OWNER myapp;`. Exit with `\\q`. Never use the `postgres` role in your application connection string — a bug or injection would operate with superuser rights.",{"title":93,"body":94},"Configure postgresql.conf for expected load","The configuration file is at `\u002Fetc\u002Fpostgresql\u002F17\u002Fmain\u002Fpostgresql.conf`. Key parameters for a 4 GB VPS: `shared_buffers = 1GB` (25% of RAM), `effective_cache_size = 3GB`, `work_mem = 16MB`, `maintenance_work_mem = 256MB`, `max_connections = 100`. Restart after any change: `sudo systemctl restart postgresql`. For an 8 GB VPS, raise `shared_buffers` to 2 GB and `effective_cache_size` to 6 GB.",{"title":96,"body":97},"Restrict network connections in pg_hba.conf","By default, PostgreSQL only listens on `localhost`. If your application is on the same server, leave it as is. For an application on another machine, edit `\u002Fetc\u002Fpostgresql\u002F17\u002Fmain\u002Fpg_hba.conf` and add: `host myapp myapp \u003Capp-IP>\u002F32 scram-sha-256`. In `postgresql.conf`, set `listen_addresses = 'localhost,\u003CVPS-IP>'`. Reload: `sudo systemctl reload postgresql`.",{"title":99,"body":100},"Export from RDS and import on the VPS","From a machine with access to both hosts, export using the custom format: `pg_dump -h \u003Crds-endpoint> -U \u003Cuser> -Fc \u003Cdatabase> -f dump.pgc`. Then import on the VPS in parallel across 4 workers: `pg_restore -h localhost -U myapp -d myapp -j 4 dump.pgc`. Verify row counts on a few critical tables before switching the application connection.",{"title":102,"body":103},"Automate backups with a cron job","Create `\u002Fusr\u002Flocal\u002Fbin\u002Fpg-backup.sh`: `PGPASSWORD='password' pg_dump -U myapp myapp -Fc > \u002Fvar\u002Fbackups\u002Fpg\u002Fmyapp-$(date +%Y%m%d-%H%M).pgc`. Make it executable: `chmod +x \u002Fusr\u002Flocal\u002Fbin\u002Fpg-backup.sh`. Add the crontab entry: `0 3 * * * \u002Fusr\u002Flocal\u002Fbin\u002Fpg-backup.sh`. Keep dumps encrypted on external storage or transfer them via `rsync` to a second VPS for an off-site copy.",{"title":105,"body":106},"Enable monitoring with pg_stat_statements","In `postgresql.conf`, add `shared_preload_libraries = 'pg_stat_statements'`. Restart PostgreSQL, then activate the extension in your database: `CREATE EXTENSION pg_stat_statements;`. Identify slow queries: `SELECT query, mean_exec_time, calls FROM pg_stat_statements ORDER BY mean_exec_time DESC LIMIT 10;`. This replaces RDS Performance Insights for daily diagnosis.",{"type":108,"body":109},"tip","**Post-install hardening**: disable the system `postgres` account for SSH connections (`sudo passwd -l postgres`); enable `ssl = on` in `postgresql.conf` with a Let's Encrypt or self-signed certificate to encrypt network connections between the application and the database; enable `ufw` and open port `5432` only to known application IPs (`sudo ufw allow from \u003Capp-IP> to any port 5432`). These three steps cover the essential attack surface of a database exposed on a non-private network.",{"type":29,"title":111,"body":112},"Troubleshooting: common errors after migration","The errors below appear frequently in the first hours after an RDS-to-VPS migration. Each has a precise message and a targeted remedy — read the full message before acting, as several distinct causes share the same error code.",{"type":33,"title":114,"items":115},"Five common errors and their solutions",[116,117,118,119,120],"**`FATAL: password authentication failed for user \"myapp\"`** — the password sent does not match the one stored, or the authentication method differs (`md5` vs `scram-sha-256`). Check the corresponding line in `pg_hba.conf` and reload: `sudo systemctl reload postgresql`. If you changed the password from psql, make sure the application connection string reflects the new one.","**`FATAL: no pg_hba.conf entry for host \"\u003CIP>\", user \"myapp\", database \"myapp\", SSL off`** — the source IP of the connection is not authorised in `pg_hba.conf`. Add the missing entry for that IP and reload. If you are not using SSL, make sure the line uses `host` and not `hostssl`.","**`ERROR: extension \"uuid-ossp\" does not exist`** (or any extension absent on RDS) — the extension is available in PostgreSQL but not enabled in this database. Run from psql: `CREATE EXTENSION IF NOT EXISTS \"uuid-ossp\";`. If the extension is absent from the package, install it: `sudo apt install postgresql-17-\u003Cextension>`.","**`FATAL: remaining connection slots are reserved for non-replication superuser connections`** — `max_connections` is reached. Increase it in `postgresql.conf` and restart, or install `pgBouncer` to pool connections: a pool of 10 real connections can serve hundreds of application clients.","**`pg_restore: error: could not execute query: ERROR: role \"rdsadmin\" does not exist`** — RDS creates internal roles absent from any non-AWS PostgreSQL. Add `--no-owner --no-privileges` to `pg_restore`: `pg_restore --no-owner --no-privileges -h localhost -U myapp -d myapp dump.pgc`. Objects are imported without attempting to reassign ownership to RDS roles.",{"type":29,"title":122,"body":123},"What this comparison does not cover — and what to know before deciding","Self-hosting transfers to your team the management of backups, security updates and monitoring. This is a reality, not an argument against it — evaluate it against the cost saved. For a solo developer or a small team without operational expertise, the VPS administration option covers routine tasks — updates, monitoring, verified backups — without you having to orchestrate them. RDS remains relevant in two specific situations: when multi-region resilience is a contractual requirement and you lack the resources to implement it manually, and when consumption-based billing genuinely suits a very small, rarely-accessed database (a VPS runs and is billed 24\u002F7 even at zero load). For everything else — mid-sized database, stable workload, team with basic system skills — the numbers clearly favour self-hosting. The articles \u003Ca href=\"\u002Fblog\u002Fheberger-postgresql-vps\">PostgreSQL on VPS: installation and best practices\u003C\u002Fa> and \u003Ca href=\"\u002Fblog\u002Fpostgresql-fin-de-vie-planifier-montee-version\">PostgreSQL end of life: planning the version upgrade\u003C\u002Fa> complement this guide on the operational and major version management side.","Deploy PostgreSQL on a dedicated-resource VPS","Root access, SSD NVMe storage, IPv4 included, no per-GB surcharge. Choose your configuration and put your database in orbit.","Deploy PostgreSQL on a dedicated-resource VPS — root access, SSD NVMe storage, IPv4 included, no per-GB surcharge.","\u002Fsolutions\u002Fdeveloppeurs",[129,143,153],{"id":130,"slug":131,"title":132,"excerpt":133,"readTime":134,"views":135,"isPinned":13,"publishedAt":136,"category":137,"categories":138,"featuredImage":23,"bgImage":24,"posterImage":140,"relatedSolution":141},56,"heberger-postgresql-vps","PostgreSQL on a VPS: a reliable and controlled database","Host PostgreSQL on a VPS: volumes, backups, restricted network access and sound configuration for your applications.",4,2240,"2026-04-25T00:00:00+00:00",{"id":16,"name":17,"slug":18,"color":19,"icon":20},[139],{"id":16,"name":17,"slug":18,"color":19,"icon":20},"\u002Fblog\u002Fcovers\u002Fheberger-postgresql-vps-poster.svg",{"categorySlug":18,"appSlug":142},"postgresql-stack",{"id":144,"slug":145,"title":146,"excerpt":147,"readTime":134,"views":12,"isPinned":13,"publishedAt":148,"category":149,"categories":150,"featuredImage":23,"bgImage":24,"posterImage":152,"relatedSolution":23},225,"postgresql-fin-de-vie-planifier-montee-version","PostgreSQL end of life: plan your major upgrade","PostgreSQL supports each major version for five years, ending in November. Find out which one you run and plan the upgrade without losing data.","2026-08-05T00:00:00+00:00",{"id":16,"name":17,"slug":18,"color":19,"icon":20},[151],{"id":16,"name":17,"slug":18,"color":19,"icon":20},"\u002Fblog\u002Fcovers\u002Fpostgresql-fin-de-vie-planifier-montee-version-poster.svg",{"id":154,"slug":155,"title":156,"excerpt":157,"readTime":134,"views":12,"isPinned":13,"publishedAt":158,"category":159,"categories":160,"featuredImage":23,"bgImage":24,"posterImage":162,"relatedSolution":23},217,"valkey-vs-redis-migration-2026","Valkey vs Redis in 2026: Comparison and Migration Guide","Redis returned to an OSI-compatible license (AGPLv3) in May 2025, but Valkey 9.1 is now the default cache package on Ubuntu, Debian and Fedora, delivering +8% ops\u002Fsec and -22% P99 latency. Here's how to choose and migrate in 4 steps.","2026-08-03T00:00:00+00:00",{"id":16,"name":17,"slug":18,"color":19,"icon":20},[161],{"id":16,"name":17,"slug":18,"color":19,"icon":20},"\u002Fblog\u002Fcovers\u002Fvalkey-vs-redis-migration-2026-poster.svg",1786296242842]