{"id":104,"date":"2026-10-08T16:45:00","date_gmt":"2026-10-08T16:45:00","guid":{"rendered":"https:\/\/top.fadah.store\/?p=104"},"modified":"2026-10-08T16:45:00","modified_gmt":"2026-10-08T16:45:00","slug":"automate-postgres-backup-s3-python","status":"publish","type":"post","link":"https:\/\/top.fadah.store\/?p=104","title":{"rendered":"Automating Daily PostgreSQL Backups to AWS S3 in Under 50 Lines of Python"},"content":{"rendered":"<p>Relying on manual database dumps is a recipe for disaster. I wrote a lightweight, self-contained Python script to dump a remote Postgres database, compress it with gzip, and upload it directly to an Amazon S3 bucket with date versioning.<\/p>\n<h2>The Script<\/h2>\n<pre class=\"wp-block-code\"><code class=\"language-python\">import os\nimport subprocess\nfrom datetime import datetime\nimport boto3\n\nDB_NAME = \"production_db\"\nDB_USER = \"postgres\"\nDB_HOST = \"localhost\"\nS3_BUCKET = \"company-db-backups-secure\"\n\ntimestamp = datetime.now().strftime(\"%Y-%m-%d_%H-%M-%S\")\nbackup_filename = f\"{DB_NAME}_{timestamp}.sql.gz\"\n\n# 1. Run pg_dump piped into gzip\ndump_cmd = f\"pg_dump -h {DB_HOST} -U {DB_USER} {DB_NAME} | gzip > {backup_filename}\"\nsubprocess.run(dump_cmd, shell=True, check=True)\n\n# 2. Upload to S3\ns3 = boto3.client(\"s3\")\ns3.upload_file(backup_filename, S3_BUCKET, f\"postgres\/{backup_filename}\")\n\n# 3. Clean local file\nos.remove(backup_filename)\nprint(f\"Successfully uploaded {backup_filename} to S3!\")<\/code><\/pre>\n<h2>Retention Policy<\/h2>\n<p>By pairing this Python script with an AWS S3 Lifecycle rule that deletes objects older than 30 days, we achieved zero-maintenance database backups for pennies a month.<\/p>\n","protected":false},"excerpt":{"rendered":"<p>Relying on manual database dumps is a recipe for disaster. I wrote a lightweight, self-contained Python script to dump a remote Postgres database, compress it with gzip, and upload it directly to an Amazon S3 bucket with date versioning. The Script import os import subprocess from datetime import datetime import boto3 DB_NAME = &#8220;production_db&#8221; DB_USER &#8230; <a title=\"Automating Daily PostgreSQL Backups to AWS S3 in Under 50 Lines of Python\" class=\"read-more\" href=\"https:\/\/top.fadah.store\/?p=104\" aria-label=\"Read more about Automating Daily PostgreSQL Backups to AWS S3 in Under 50 Lines of Python\">Read more<\/a><\/p>\n","protected":false},"author":2,"featured_media":0,"comment_status":"open","ping_status":"closed","sticky":false,"template":"","format":"standard","meta":{"footnotes":""},"categories":[3],"tags":[16,17,13,9],"class_list":["post-104","post","type-post","status-publish","format-standard","hentry","category-python","tag-aws-s3","tag-devops","tag-postgresql","tag-python"],"_links":{"self":[{"href":"https:\/\/top.fadah.store\/index.php?rest_route=\/wp\/v2\/posts\/104","targetHints":{"allow":["GET"]}}],"collection":[{"href":"https:\/\/top.fadah.store\/index.php?rest_route=\/wp\/v2\/posts"}],"about":[{"href":"https:\/\/top.fadah.store\/index.php?rest_route=\/wp\/v2\/types\/post"}],"author":[{"embeddable":true,"href":"https:\/\/top.fadah.store\/index.php?rest_route=\/wp\/v2\/users\/2"}],"replies":[{"embeddable":true,"href":"https:\/\/top.fadah.store\/index.php?rest_route=%2Fwp%2Fv2%2Fcomments&post=104"}],"version-history":[{"count":0,"href":"https:\/\/top.fadah.store\/index.php?rest_route=\/wp\/v2\/posts\/104\/revisions"}],"wp:attachment":[{"href":"https:\/\/top.fadah.store\/index.php?rest_route=%2Fwp%2Fv2%2Fmedia&parent=104"}],"wp:term":[{"taxonomy":"category","embeddable":true,"href":"https:\/\/top.fadah.store\/index.php?rest_route=%2Fwp%2Fv2%2Fcategories&post=104"},{"taxonomy":"post_tag","embeddable":true,"href":"https:\/\/top.fadah.store\/index.php?rest_route=%2Fwp%2Fv2%2Ftags&post=104"}],"curies":[{"name":"wp","href":"https:\/\/api.w.org\/{rel}","templated":true}]}}