Cloudflare Cost Security & compliance

Large R2 bucket storage (storage cost)

Part of the Workers, Pages & API tokens check · fix arrives as a guide

What it is

An R2 bucket holds a large volume of stored data.

Why it matters

R2 bills on storage, so a bucket that only grows is a line item that only grows. Buckets accumulating build artifacts, logs, or old uploads are the usual cause, and nothing prompts a review.

How R2 charges — and where the surprise lives

R2 bills three meters: stored gigabytes per month, Class A operations (writes, lists) and Class B operations (reads). Egress is free — the reason teams pick R2 — which means the bill is almost entirely a function of how much you store and how often you touch it. Storage cost is a ratchet: every object you never delete bills again every month, so a bucket that only ever grows produces a bill that only ever grows.

The two classic silent accumulators

Buckets that get large without anyone deciding to store that much usually contain one of these:

1. Build artifacts and backups on a schedule with no expiry — nightly dumps, per-deploy bundles, log exports. Each one small; three years of them, not. 2. Incomplete multipart uploads — a client that crashed mid-upload leaves its parts behind, invisible in object listings but billed as storage, forever, unless a rule aborts them.

See what a bucket actually holds

# object count and total size (dashboard: R2 → bucket → Metrics) wrangler r2 bucket info YOUR_BUCKET # spot-check the oldest objects — are they still worth paying for? wrangler r2 object list YOUR_BUCKET --limit 20

Fix it manually — lifecycle rules

R2 lifecycle rules delete or expire objects on a schedule, per bucket, optionally scoped by prefix (R2 → bucket → Settings → Object lifecycle rules). The two rules almost every bucket wants:

Rule 1: abort incomplete multipart uploads after 7 days Rule 2: expire objects under a dated prefix past its useful life, e.g. backups/ after 90 days, build-artifacts/ after 30

Keep what you would actually restore from; a backup nobody would dare restore is storage cost wearing a safety blanket.

How lumioguard fixes it

The scan reads bucket sizes and lifecycle configuration on every run and flags growth with no expiry rules behind it. The fix arrives as a guide with the lifecycle rules matched to the prefixes actually present in the bucket.

Run them all on your app

Connect your repo and your live services with read-only scopes. The first scan is free, and nothing changes without your approval.