The short route: stream pg_dump straight into aws s3 cp
To back up Postgres to S3, pipe pg_dump into aws s3 cp and use a dash as the source, which tells the AWS CLI to read from standard input:
pg_dump -Fc mydb | aws s3 cp - s3://amzn-s3-demo-bucket/postgres/mydb.dump
Both halves are documented. The pg_dump reference says the custom format (-Fc) is compressed by default and that output goes to standard output when -f is omitted. The AWS CLI reference for s3 cp shows the dash form for uploading a stream. Nothing touches local disk, which matters when the server has little free space.
We may earn a commission if you buy through links on this page, at no extra cost to you.
See current SimpleBackups plans →Prerequisites before the first upload
- PostgreSQL client tools on the machine that runs the job.
pg_dumprefuses to dump from a server newer than its own major version, so match or exceed the server version. - A database role that can read every table. The manual notes that backing up an entire database almost always means running as a superuser.
- No password prompt. For scripts, keep the password in a
.pgpassfile and add--no-passwordso a missing password fails instead of hanging. - AWS CLI configured with credentials allowed to write objects to the bucket.
- No paid plan is needed. pg_dump ships with PostgreSQL; you pay AWS for the S3 storage you use.
Step by step, with the flags that matter
- Dump roles separately.
pg_dumpdoes not save roles or tablespaces. Runpg_dumpall --globals-only | aws s3 cp - s3://amzn-s3-demo-bucket/postgres/globals.sql. This file contains role definitions, so restrict access to it. - Stream the database. Run the
pg_dump -Fc mydb | aws s3 cp - ...command above, with a date in the object key so each run is kept. - Tell the CLI the size of big streams. The AWS reference says
--expected-size(in bytes) is needed when a stream is larger than 50 GB; without it the upload can fail at the default limit of 10,000 parts. - Encrypt and pick a storage class if you want.
--sse AES256requests server-side encryption.--storage-class STANDARD_IAis one of the documented choices; the default is STANDARD. - Confirm the object exists and has a sane size.
aws s3 ls s3://amzn-s3-demo-bucket/postgres/ --human-readable --summarize - Expire old backups. An S3 Lifecycle expiration action deletes objects after the age you set, so the script does not need its own cleanup.
Worked example: a nightly dump and a test restore from S3
A team with one application database called shop runs this from cron each night:
pg_dump -Fc --no-password shop | aws s3 cp - s3://amzn-s3-demo-bucket/postgres/shop-2026-10-03.dump --sse AES256
The wrapper script starts with set -o pipefail, so a failed dump makes the whole pipeline fail, and it substitutes the current date into the object key on each run, for example with $(date +%F). If you put the command straight into a crontab line instead, write every % as \%: cron treats an unescaped percent sign as a newline.
Once a week they prove it restores. They download one object, create an empty database from template0 as the manual advises, and restore into it:
aws s3 cp s3://amzn-s3-demo-bucket/postgres/shop-2026-10-03.dump shop.dump
createdb -T template0 shop_restore_test
pg_restore -d shop_restore_test shop.dump
Downloading first, instead of piping, keeps the option of pg_restore -j for a parallel restore, which the manual says requires a regular file and not a pipe. Then run a few acceptance checks on row counts and recent records.
A mistake to guard against: a pipeline that reports success after pg_dump fails
In a shell pipeline the exit status normally comes from the last command. If pg_dump dies halfway, aws s3 cp can still upload the partial stream and exit zero, leaving a truncated object that looks like a backup. Guard against it by running the script under bash with set -o pipefail at the top, which makes the pipeline return the failing command's status, then alerting on a non-zero exit, and watching object sizes with aws s3 ls. A sudden drop in size is the warning sign. The only complete proof is the test restore above.
A second limit: this route restores to the time of the dump only. Point-in-time recovery needs a physical base backup and archived WAL. pgBackRest and WAL-G both document S3 as a repository for that; see dump versus point-in-time recovery.
The managed alternative to a hand-written S3 script
The script above is enough for one or two databases with an owner who reads the alerts. It becomes fragile when databases multiply or the person who wrote it leaves. SimpleBackups runs the schedule for you, lets you connect your own cloud storage on every plan, and sends failure notifications. As read on its pricing page on 3 October 2026, Basic is $0 for one job and Lite is $49 per month for five jobs, with a 5 GB maximum database size on Lite. Managed versus scripted backups sets out the trade.
Sources used for this page
The facts above come from the pages below, read on 3 October 2026. We have not used these products hands-on. Prices and terms change, so confirm them on the vendor's site before you buy.
- PostgreSQL Documentation: pg_dump — Vendor documentation · postgresql.org · checked 2026-10-03
- PostgreSQL Documentation: pg_dumpall — Vendor documentation · postgresql.org · checked 2026-10-03
- PostgreSQL Documentation: pg_restore — Vendor documentation · postgresql.org · checked 2026-10-03
- PostgreSQL Documentation: 25.1. SQL Dump — Vendor documentation · postgresql.org · checked 2026-10-03
- AWS CLI Command Reference: s3 cp — Vendor documentation · docs.aws.amazon.com · checked 2026-10-03
- AWS CLI User Guide: Using high-level (s3) commands in the AWS CLI — Vendor documentation · docs.aws.amazon.com · checked 2026-10-03
- AWS CLI Command Reference: s3 ls — Vendor documentation · docs.aws.amazon.com · checked 2026-10-03
- Amazon S3 User Guide: Managing the lifecycle of objects — Vendor documentation · docs.aws.amazon.com · checked 2026-10-03
- pgBackRest: Reliable PostgreSQL Backup and Restore — Vendor documentation · pgbackrest.org · checked 2026-10-03
- WAL-G documentation: WAL-G for PostgreSQL — Vendor documentation · github.com · checked 2026-10-03
- SimpleBackups Pricing — Vendor pricing page · simplebackups.com · checked 2026-10-03
- bash(1) Linux manual page: pipelines and the pipefail option — Independent · man7.org · checked 2026-10-03
- crontab(5) Linux manual page — Independent · man7.org · checked 2026-10-03