Why is your storage bill mostly egress?
Object storage is cheap to put in (S3 is $0.023/GB-month). The killer is moving data out: S3 egress is $0.09/GB to the internet — five orders of magnitude more than storage itself. Add per-operation fees, multi-region replication costs, and the engineering overhead of connecting a centralized database to edge code, and your 'cheap' cloud-storage stack quickly becomes very expensive and very slow.
How it fits together
Diagram coming soon
Architecture diagram for this solution will be added here.
How Cloudflare solves it
| R2 | D1 | KV | |
|---|---|---|---|
| What it is | Object storage | Serverless SQL database | Global key-value store |
| Comparable to | AWS S3 | PlanetScale / SQLite Cloud | Redis / DynamoDB |
| Optimal use case | Files, media, AI training data, backups | Relational data — queries, joins, transactions | Config, feature flags, session tokens, cached data |
| Real-world example | Product images, user uploads, video & backup assets | Product catalog, order history, user accounts | A/B test flags, rate-limit counters, cached API results |
| Pricing model | Storage + operations, $0 egress | Rows read / written, scale-to-zero compute | Reads / writes / storage |
| Worker binding | env.MY_BUCKET.put() | env.MY_DB.prepare() | env.MY_KV.get() |
| Notable | S3-compatible API · Super Slurper migration tool | Point-in-time restore (time travel, last 30 days) | Reads served from local edge cache · updates propagate globally in seconds |
Common questions
Is R2 really free egress, no asterisks?
When should I use D1 vs KV?
Is D1 production-ready?
How do I migrate from S3 to R2?
Try it live
Upload a file to R2 (as guest with email, or via Cloudflare Access auth). Malicious-content detection scans every upload. Pricing calculator compares R2 storage and egress vs S3, GCS, Azure, and Vercel.
R2 is S3-compatible object storage with $0 egress. Upload a file below (as a guest — your email just tags the file), then use the calculator to compare R2's bill against the hyperscalers on a read-heavy workload.
1. Upload to R2
Every file is scanned for malicious content before it's accepted. Max 50 MB. Allowed types: PDF, CSV, PNG, JPG, GIF, DOC(X), PPT(X), TXT.
Your email
Used only to tag the upload so it can be attributed to you.
Choose a file
Selected: ()
2. Pricing calculator: R2 vs the rest
Estimate monthly cost for a given workload. R2 has $0 egress — the dramatic differentiator on read-heavy workloads.
In millions. Writes & lists.
In millions. Reads (GET, HEAD).
| Provider | Storage | Egress | Operations | Total / mo |
|---|---|---|---|---|
Pricing verified June 2026. Standard storage tiers, US regions. Hyperscaler egress and ops pricing varies by region & tier; figures reflect commonly-cited public list prices. R2 egress is $0 to any internet destination, billed only for storage and operations.
Workers KV is a global key-value store. Writes propagate to every Cloudflare location within seconds; reads are served from the cache nearest the user. Reach for KV when you have a flat key → value lookup and want the fastest possible global reads: config, feature flags, session tokens, cached API responses.
Key
Value
Keys in the store
D1 is a serverless SQL database (SQLite-compatible) that runs
at the edge. Reach for D1 when you need relational queries, joins, or
transactions. Run a preset query against a seeded products table —
the exact SQL and rows-read are shown so you can see what D1 did.
Query executed
Rows read: · Rows returned:
Query error
If the table doesn't exist yet, seed it once with
npx wrangler d1 execute demo-d1 --remote --file=db/demo-d1-seed.sql.