Railway

Deploy PostgreSQL S3 backups

A simple utility to backup Postgres databases to S3 using Bun.

Deploy PostgreSQL S3 backups

PostgreSQL S3 Backups

ncontiero/postgres-s3-backups

Just deployed

Deploy and Host PostgreSQL S3 backups on Railway

PostgreSQL S3 backups is a lightweight service that creates compressed PostgreSQL backups and uploads them to AWS S3, Cloudflare R2, MinIO, or another S3-compatible storage provider. Run it continuously with Bun's native scheduler or once per deployment with Railway Cron.

About Hosting PostgreSQL S3 backups

Hosting PostgreSQL S3 backups involves connecting the service to a PostgreSQL database and an S3-compatible bucket through Railway variables. For each execution, the service streams pg_dump into a Gzip-compressed tar archive, validates it, uploads it, and removes the temporary local file. It supports automatic multipart uploads, configurable retention, custom pg_dump options, and PostgreSQL client versions 14 through 18. You can use Railway Cron to start one single-shot deployment per schedule or keep the service running with Bun's native scheduler. No persistent volume or separate Bun runtime installation is required in the final Docker image.

Common Use Cases

  • Schedule PostgreSQL backups to off-site S3-compatible storage.
  • Apply a configurable retention period to control storage usage.
  • Back up Railway PostgreSQL services without maintaining a separate backup server.

Dependencies for PostgreSQL S3 backups Hosting

  • A reachable PostgreSQL database and its DATABASE_URL.
  • An AWS S3 or S3-compatible bucket with credentials that can upload objects. Listing and deleting objects are also required when retention is enabled.

Implementation Details

Deployment modes
  • Railway Cron (recommended): Set SINGLE_SHOT_MODE=true and configure a Cron Schedule in the Railway service settings. Railway starts the service for each execution, and the process exits when the backup finishes. Railway schedules use UTC, support a minimum interval of five minutes, and skip an execution if the previous one is still active. BACKUP_CRON_SCHEDULE and RUN_ON_STARTUP are not used in this mode.
  • Continuous service: Keep SINGLE_SHOT_MODE=false and configure BACKUP_CRON_SCHEDULE. The standalone application remains active and schedules backups with Bun's native cron implementation. Set RUN_ON_STARTUP=true to back up immediately when the service starts. Overlapping executions are skipped.
Required configuration

When PostgreSQL is another Railway service, use a reference variable. Replace Postgres if the database service has a different name.

DATABASE_URL=${{Postgres.DATABASE_URL}}

AWS_ACCESS_KEY_ID=your-access-key-id
AWS_SECRET_ACCESS_KEY=your-secret-access-key
S3_BUCKET=your-bucket-name
S3_REGION=us-east-1

Set S3_ENDPOINT when using a provider other than AWS:

S3_ENDPOINT=https://your-s3-compatible-endpoint
Environment variables
VariableDescriptionDefault
AWS_ACCESS_KEY_IDS3 access key ID.Required
AWS_SECRET_ACCESS_KEYS3 secret access key.Required
S3_BUCKETDestination bucket name.Required
S3_REGIONDestination bucket region.Required
S3_ENDPOINTCustom endpoint for an S3-compatible provider.
DATABASE_URLPostgreSQL connection URL.Required
BACKUP_CRON_SCHEDULEFive-field cron schedule used in continuous mode.0 0 * * *
BACKUP_FILE_PREFIXPrefix used in backup object names.backup
BACKUP_RETENTION_DAYSDelete matching backups older than this number of days.
BUCKET_SUBFOLDEROptional bucket path in which backups are stored.
BACKUP_OPTIONSAdditional space-separated arguments passed to pg_dump.
RUN_ON_STARTUPRun a backup when a continuous service starts. Accepts true, false, 1, 0.false
SINGLE_SHOT_MODERun one backup and exit. Accepts true, false, 1, 0.false

PG_VERSION is a Docker build argument rather than a runtime variable. It accepts versions 14 through 18, defaults to 18, and should preferably match the database server's major version.

Backup behavior

Backups are named <prefix>-<ISO timestamp>.tar.gz. The service creates a PostgreSQL tar archive, compresses it with Gzip, validates the expected archive entries, and uploads it using Bun's S3 client. Bun automatically uses multipart uploads when appropriate. A dump, validation, or upload failure makes single-shot mode exit with status 1; continuous mode logs the error and keeps future executions scheduled. Retention and temporary-file cleanup errors are reported separately and do not invalidate an already uploaded backup.

To restore a downloaded backup, decompress it and pipe the archive into a compatible pg_restore client:

gzip --decompress --stdout backup.tar.gz \
  | pg_restore --dbname="postgresql://user:password@host:port/database"

For more information, see the documentation for Railway Cron, Bun S3, pg_dump, and pg_restore.

Why Deploy PostgreSQL S3 backups on Railway?

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 PostgreSQL S3 backups 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.


Template Content

PostgreSQL S3 Backups

ncontiero/postgres-s3-backups

More templates in this category

View Template
N8N Main + Worker
Deploy and Host N8N with Inactive worker.

jakemerson
119
View Template
Evolution API with n8n
Automate WhatsApp workflows with Evolution API, n8n, and Postgres.

codestorm
82
View Template
Postgres Backup
Cron-based PostgreSQL backup to bucket storage

Railway Templates
870