Cloudflare D1 read replicas: what it unlocks and where it still falls short
D1 read replicas shipped in August 2025. The architecture is interesting and the unlocks are real — but the limits matter for production planning.
Cloudflare shipped D1 read replicas to general availability in August 2025. For apps running on Workers + D1, this closes one of the biggest gaps versus Neon / Supabase Postgres — globally-distributed reads are now possible without complex application logic.
After testing on a real production workload through the beta and now into GA, here is the honest read.
What actually shipped
D1 read replicas let you:
- Create a primary D1 database in a specific region
- Spawn read replicas in other regions
- Workers query the nearest replica for reads
- Writes go to the primary; replicas catch up asynchronously
The architecture is conceptually similar to Postgres streaming replication or AWS Aurora’s read replicas — eventual consistency on the read replicas, with replication lag typically in the tens of milliseconds.
What this unlocks:
- Reads from anywhere in under 50ms — without it, every read had to roundtrip to the primary region
- Higher read throughput — replicas absorb read load, primary handles writes
- Lower cost than Durable Object alternatives for read-heavy workloads
What it doesn’t solve
Real limits to plan for:
Replication lag matters. If your app writes data and immediately reads it back, the read may hit a replica that hasn’t caught up. The “read your own writes” guarantee requires either pinning to primary for the read, or accepting potential staleness. D1 provides a “read from primary” option for this case, but you have to opt in.
No SQLite multi-writer. SQLite has one writer at a time per database. Replicas can serve reads in parallel; writes still serialize through the primary. For high-write workloads this is the actual scaling ceiling — not replica count.
Cost is per-replica. Each read replica is an additional cost line item. Multi-region setups are no longer “free” the way single-region D1 was.
Schema sync timing. Migrations run on the primary first, then propagate. Brief windows where the schema differs between primary and replicas can produce confusing errors. Plan migrations during low-traffic windows.
How to actually use it
For a read-heavy app (typical SaaS), the working pattern:
// Default: read from nearest replica (low latency)
const article = await env.DB.prepare('SELECT * FROM articles WHERE id = ?').bind(id).first();
// When you need read-your-own-writes consistency:
const article = await env.DB.withSession('first-primary').prepare('SELECT * FROM articles WHERE id = ?').bind(id).first();
The session API lets you pin a sequence of reads/writes to consistent ordering. For most read paths you don’t need it; for the “just-wrote, now-reading” path you do.
How D1 + replicas compares to alternatives
| D1 + replicas | Neon Postgres | Aurora Postgres | |
|---|---|---|---|
| Read latency at edge | under 50ms via replicas | HTTP API ~100ms | Reads from regional replicas |
| Write latency | Primary-region round-trip | Primary-region round-trip | Primary-region round-trip |
| Free tier | Real | Real | None |
| Multi-region replication | Yes (new) | Yes (newer) | Yes |
| Multi-writer | No (SQLite limit) | No (single primary) | No (single primary) |
| Read replicas auto-managed | Yes | Yes | Yes |
For workloads that fit in SQLite, D1 + replicas is now competitive with managed Postgres for read-heavy use cases.
Where this actually changes the architecture math
Three concrete shifts in 2025:
1. Single-region D1 → multi-region D1 is now a sensible upgrade path. Apps that started in one region can grow into multi-region without database rewrite.
2. The “should I use Durable Objects or D1?” decision shifts. Previously, single-region D1 made you reach for Durable Objects to scale reads. With replicas, plain D1 covers more workloads.
3. The “Workers + D1” stack is now a serious Postgres competitor for many SaaS apps. Not all — SQLite still has limits, multi-row transactions still need Durable Objects — but the gap closes meaningfully.
What r/CloudFlare is saying
The community signal post-launch:
- General positive reception — “finally” is the recurring sentiment
- Concerns about per-replica pricing — careful budgeting matters at multi-region scale
- Real-world replication-lag reports cluster around 20-50ms typical, 100-200ms 99th percentile
The honest take
D1 read replicas turn D1 from “good for single-region workloads” into “credible for many multi-region workloads.” Not all — write-heavy and complex-transaction workloads still need different tools — but a meaningful slice of SaaS apps that previously needed Postgres can now live on D1.
For TopInsight, we’ll add D1 with replicas for the upcoming editorial pipeline state. The cost is manageable and the latency at edge is the killer feature for our globally-distributed reader base.
See our Workers + D1 production guide for the broader stack pattern, and the Neon vs Supabase vs PlanetScale piece for the Postgres alternatives.
Sources
Every reference behind this piece. If we make a claim, it's because at least one of these said so — or we lived it ourselves.
- Firsthand Tested D1 read replicas on a production workload
- Docs Cloudflare D1 read replicas documentation — Cloudflare
- Blog r/CloudFlare — D1 and Workers production discussions — r/CloudFlare
- YouTube Cloudflare developer advocates on read replicas — Various