Skip to content

fix(backup): enforce B2 retention so nightly dumps can't exceed the storage cap - #202

Merged
Oscar-west merged 1 commit into
mainfrom
fix/backup-b2-retention
Sep 10, 2026
Merged

Oscar-west merged 1 commit into
mainfrom
fix/backup-b2-retention

Conversation

@Oscar-west

Copy link
Copy Markdown
Contributor

Why

scripts/backup.sh shipped a new ~380 MB pg_dump to Backblaze B2 every night and pruned nothing. The kibarometer-backups bucket grew unbounded and hit the 10 GB storage cap on 2026-09-09 — two nights (09-09, 09-10) failed silently with 403 storage_cap_exceeded, and the Sunday weekly snapshot had been dead since May. Live data was never at risk; the offsite copy just stopped updating.

What

  • Retention before upload: keep the newest NIGHTLY_KEEP (14) and WEEKLY_KEEP (6) dumps — both env-overridable. Pruning runs before the upload (to KEEP-1, so the new dump restores KEEP), so a bucket already at the cap trims itself and self-heals instead of wedging.
  • Actually frees space: set hard_delete = true and run rclone cleanup. On a versioned B2 bucket, rclone delete only hides objects and the hidden versions keep counting toward the cap — which is why a manual prune during the incident didn't clear 403 until rclone cleanup purged the hidden versions.
  • Dumps are date-named, so "keep newest N" is a lexical sort + head.

Notes

  • Steady state ≈ 14 nightly + 6 weekly ≈ 7.6 GB at current dump size; dumps grow with the dataset, so the 10 GB cap may still need raising over time (separate, account-level Backblaze action).
  • Verified sh -n clean. I'll exercise it live (docker exec kiba-backup /backup.sh) once the account-level B2 cap is cleared and this is deployed.

🤖 Generated with Claude Code

…torage cap

backup.sh copied a new ~380 MB pg_dump to Backblaze B2 every night and pruned
nothing, so the bucket grew unbounded and hit the 10 GB storage cap on
2026-09-09 — two nights of backups silently failed with 403
storage_cap_exceeded, and the Sunday weekly had already been dead since May.

Add retention that runs BEFORE the upload (keep last NIGHTLY_KEEP=14 /
WEEKLY_KEEP=6, both env-overridable), so a bucket sitting at the cap trims
itself and self-heals instead of wedging. Critically, set `hard_delete = true`
and run `rclone cleanup`: on a versioned B2 bucket `rclone delete` only hides
objects and the hidden versions keep counting toward the cap — the exact reason
a plain prune didn't free space during the incident.

Co-Authored-By: Claude Opus 4.8 <noreply@anthropic.com>
@Oscar-west
Oscar-west merged commit f78c2c5 into main Sep 10, 2026
2 checks passed
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

1 participant