· database / edge / cloudflare

Edge database tradeoffs: when latency is a lie

Edge databases cut read latency globally, but writes still go to a single primary. When D1, Turso, Neon, or PlanetScale makes sense — and when Postgres wins.

By

2,438 words · 13 min read

Imagine a user in Sydney. Your app runs on Cloudflare Workers, backed by a D1 database you chose specifically for low-latency global access. When that user reads their feed, a replica answers in under 5 ms. When they sign up — write their account to the database for the first time — the request crosses the Pacific to the US primary. Round-trip: roughly 150 ms. A standard Postgres instance in Sydney would have done it in under 5 ms.

That is the trade, and the marketing rarely leads with it. Edge databases solve the read-latency problem for globally distributed users. They don’t solve the write-latency problem, because that problem is physics.

Who this is for

Developers evaluating Cloudflare D1, Turso, Neon, or PlanetScale — or anyone already running an edge deployment who wonders why writes feel slow. If your users are concentrated in a single country and you’re not operating at global scale, skip to the decision matrix. The edge story probably doesn’t apply to you.

What “edge database” actually means

The term covers four different architectures, and each has its own tradeoff profile.

Read replicas at the edge. A single write primary lives in one region. Replicas deploy close to users. Reads are fast; writes travel to the primary no matter where the user is. Cloudflare D1 works this way since its global read-replication beta in April 2025.

Multi-primary distributed databases. No single primary; any node accepts writes and replicates to peers. True multi-primary systems — CockroachDB, AlloyDB Omni — can accept writes anywhere. None of the four platforms in this article are fully multi-primary. D1, Turso, Neon, and PlanetScale all have a single authoritative write path.

Serverless with cold starts. Neon separates storage from compute and suspends idle compute automatically. You don’t pay for idle time. The cost: the first query after suspension takes 300–800 ms. It’s not “edge” in the geographic sense, but it shares the serverless billing model people associate with edge databases.

Embedded and local replicas. Turso’s current model: a SQLite file lives on your server, syncs with a remote primary. Reads hit local disk — sub-millisecond. Writes sync to the primary over the network. You get local-speed reads at the cost of managing a sync model.

Understanding which category a database belongs to tells you exactly where the latency will hurt.

The tradeoffs

Read latency — the part that works

If your users are spread across multiple continents and reads dominate your workload (90%+ is a realistic threshold), edge databases deliver real results.

Cloudflare’s own beta data, published during the D1 read-replication rollout, shows replica confirm lag between regions:

Primary → ReplicaLag
US East → US West45 ms
US East → EU West55 ms
US East → EU East67 ms
US West → EU East75 ms

A warm replica co-located with a Cloudflare Worker answers reads in 0.5–5 ms at p50 to p99. The replication lag above is how long after a write the replica reflects it — not the read latency itself.

Turso’s embedded replica benchmark measured approximately 624 µs average read latency — faster than any network query. If you control the server and can embed the SQLite file, local reads are genuinely in a different performance category.

One thing to note: Neon branching is a development tool, not a read-scaling feature. Branches use copy-on-write storage and are fast to create, but they don’t bring reads closer to users. Don’t build a read-distribution strategy around them.

Write latency — the part that isn’t

Every platform in this article serializes writes through a single primary. That means write latency is geography: the cost of a round-trip between the user’s request and wherever the primary lives.

D1: Cloudflare doesn’t publish direct write-latency measurements for far-region users. The Sydney-to-US-primary figure (~150 ms) is estimated from D1 replication lag data and Pacific network round-trip statistics — not a directly measured D1 write. Treat it as a planning floor. If your primary is in the US and you have significant AU or SA traffic, measure it in your own environment before committing to the architecture.

In co-located scenarios (Worker and write primary in the same region), D1 writes run in 5–30 ms at p50. Once you cross a region boundary, that floor rises by the physical round-trip time.

Turso: Embedded replica reads are sub-millisecond, but writes sync to the primary in 20–100 ms depending on your server’s distance from the Turso primary. The sync model means your code needs to be explicit about when reads need to reflect the latest write — you can call sync() to force freshness. For a direct head-to-head of Turso and D1’s tradeoffs, see Turso vs D1.

Neon: Standard PostgreSQL over the network. All queries — reads and writes — traverse the distance between client and server. No edge shortcut on either path. For applications with globally distributed users, this is a limitation; for applications with regional users, it’s irrelevant.

PlanetScale: Covers 13 AWS and 7 GCP regions, giving you better primary placement options than most. Writes still travel to the primary. PlanetScale Vitess targets high-write MySQL workloads, not global write distribution — sharding is horizontal within a region, not cross-region.

Consistency — what happens between a write and the next read

PlatformModelThe catch
Cloudflare D1Sequential consistency via Sessions APIWithout Sessions API, stale reads after writes are possible. Sessions API only works through the Worker binding — not the REST API.
TursoACID on primary, eventual on embedded replicasReplica reads can lag until you call sync().
NeonFull PostgreSQL ACIDRead replicas use streaming replication; lag is typically under 1 s.
PlanetScale (Vitess)ACID within a keyspace/shardCross-shard operations don’t get distributed 2PC. Cross-keyspace joins and transactions are application-level sagas.

The D1 Sessions API constraint is the one most likely to bite. If you access D1 outside a Cloudflare Worker — directly via the REST API, from a non-Cloudflare environment, or through a custom routing layer — the consistency guarantee drops to “read committed.” You may read your own writes; you may not. Applications that write and immediately read back (common in profile updates, shopping carts, notification counters) need the Sessions API or a retry-on-stale strategy.

PlanetScale’s cross-shard gotcha is similarly underappreciated. Vitess is powerful for sharding a single large MySQL dataset — zero-downtime schema changes, horizontal scale. But if your data model requires joins or transactions across keyspace boundaries, you’re writing application-level consistency code. This isn’t a dealbreaker, but it’s not what most teams expect from a managed database.

Cold starts and connection overhead

Neon’s auto-suspend is the most operationally significant cold-start behavior in this group. Free tier: 300–800 ms to first query after idle (5-minute idle threshold). Production recommendation is to disable auto-suspend on paid plans. If you have a latency SLO, free-tier Neon cold starts will violate it.

D1 inside Cloudflare Workers has no connection overhead. The database binding is in-process with the Worker. No TCP handshake. No connection pooling middleware. For serverless architectures that already struggle with connection limits on traditional Postgres, this is a genuine operational simplification.

Turso deprecated scale-to-zero in January 2025 for new users (existing accounts keep the old behavior). New architecture runs always-on. That removes cold start risk but changes the cost model — you’re paying for uptime rather than per-invocation. Depending on your traffic pattern, this may be more or less expensive than the previous model.

Operational complexity

D1 has two hard limits that determine your migration ceiling before you start: 10 GB per database and 50,000 databases per account. D1 processes writes single-threaded per database; effective write throughput is query-duration dependent (community data puts simple writes in the hundreds to low thousands per second). If you hit the storage limit, you’re sharding across databases manually. Plan for this upfront if your data grows predictably.

Turso requires understanding the sync model in your application layer. Reads from an embedded replica may be stale until synced. This is explicit by design — you call sync() to pull the latest from the primary — but it’s a mental model shift compared to standard network databases where reads always reflect the current server state.

Neon is the closest to a drop-in PostgreSQL replacement. Standard drivers, standard psql, standard pg_dump. Branching is additive — you don’t have to use it if you don’t need it. The primary operational concern is compute auto-suspend and connection pooling behavior (Neon uses a PgBouncer-based proxy; the transaction-mode pooler has implications for prepared statements and advisory locks). If you’re deciding between Neon and Supabase’s managed Postgres, see Neon vs Supabase.

PlanetScale (Vitess) adds the biggest learning curve for MySQL shops. Schema changes go through PlanetScale’s branching-and-deploy workflow rather than direct ALTER TABLE. This is genuinely useful for zero-downtime migrations on large tables, but your team needs to internalize the workflow. For teams already running standard MySQL, the first migration will feel unfamiliar.

Pricing snapshot (2026-05-27)

PlatformFree tierEntry paid
Cloudflare D15M rows read/day, 100K rows written/day, 5 GB total$5/month (Workers Paid): 25B reads + 50M writes/month included
Turso500M reads/month, 10M writes/month, 5 GB$4.99/month: 2.5B reads, 25M writes, 9 GB
Neon100 compute-unit-hours/month, 0.5 GB storageNo monthly minimum; $0.106/CU-hour, $0.35/GB-month storage
PlanetScale PostgresNone (free plan removed April 2024)$5/month: single-node Postgres (PS-5 non-HA)

Neon storage dropped 80% in late 2025 following the Databricks acquisition. These numbers move. Verify before making budget commitments.

Community benchmark data

The capaj benchmark on GitHub compared PlanetScale, Neon, and Turso from Cloudflare Workers in Frankfurt, using simple SELECT queries via Drizzle ORM:

  • PlanetScale (Scaler Pro) stayed below 67 ms throughout.
  • Neon (free tier) was slower — cold starts skewed results significantly.
  • Turso (free tier) matched PlanetScale at times, but spiked to 400 ms — likely WAL sync jitter.

Read this as directional, not definitive. All three were on free or hobby tiers; Neon cold starts in particular make the comparison unfair. Frankfurt-only results don’t generalize to other regions.

Decision matrix

Use D1 or Turso if:

  • Reads make up 90%+ of your query volume.
  • Users are spread across multiple continents.
  • Writes are infrequent and latency-tolerant — user settings, published content, not financial transactions or inventory.
  • You’re already building on Cloudflare Workers (D1 is the natural fit — if you’re still evaluating Workers vs another edge runtime, see Cloudflare Workers vs Vercel Edge).
  • Database size stays under 10 GB per logical database (D1 limit).
  • You can work with eventual consistency or are prepared to implement the Sessions API correctly.

Use Neon, PlanetScale Postgres, or a traditional managed Postgres if:

  • Writes are frequent and customer-visible (checkout, payment, booking confirmation).
  • You need full ACID across multiple tables and foreign key relationships.
  • Users are concentrated in one or two regions — edge read gains are marginal for regional apps.
  • Your database exceeds 10 GB.
  • Your users are primarily in Australia, Southeast Asia, or South America, and your primary would sit in US or EU — your writes would be slower with an edge database than with a regional one.
  • You need the full SQL feature set: CTEs, window functions, lateral joins, advisory locks. SQLite (D1, Turso) supports a capable but narrower SQL dialect.

Turso embedded replicas specifically suit server-rendered applications where you control the deployment environment and want local-speed reads without co-locating your app inside Cloudflare. If you’re running on a Fly.io VM or a VPS in a specific region, an embedded replica gives you sub-millisecond reads and manageable write sync.

Caveats

Xata was not covered in this research pass. It positions as serverless Postgres plus built-in search, and belongs in any thorough edge database comparison — a future article.

The SYD→US write latency figure (~150 ms) is inferred from Cloudflare replication lag data and public network benchmarks. Cloudflare hasn’t published a direct write-latency measurement from Sydney for D1. If your application has significant AU/SA/SEA traffic, measure this yourself in a staging environment before committing.

Turso’s affiliate commission is not yet confirmed. Turso launched a partner program in May 2026. Commission details are disclosed after application review. We’re working on it — no Turso affiliate link until that’s settled.

Toolchew has applied to the Neon Open Source Program. If approved, referral links will route through /go/neon — toolchew earns $20 per referred user who spends $20+ on Neon, at no cost to you. The affiliate disclosure at the top of this article covers this relationship.

Verdict

D1 is the most operationally simple choice if you’re building on Cloudflare Workers. No connection pooling overhead, no cold starts, global reads with zero extra infrastructure. Its ceilings are real — 10 GB, 2K writes/sec — so assess whether your workload fits before committing.

Turso has the most interesting read story right now. After the January 2025 pivot away from Fly.io edge replicas, the pitch is “embed the database on your server” rather than “deploy near the user.” Microsecond reads from local disk, writes synced to the cloud. Works best when you control your deployment environment and want local-first semantics.

Neon is the right pick when you want PostgreSQL without running your own Postgres. Full SQL, standard tooling, cold starts that disappear on paid plans (always-on compute). The Databricks acquisition in May 2025 creates long-term pricing uncertainty — watch for changes.

PlanetScale fits high-write MySQL workloads that need Vitess-scale sharding, or teams that want managed Postgres without serverless billing. Budget at least $5/month from day one.

None of these beat a well-placed single-region Postgres if your users are regional. The latency wins from edge distribution require genuinely distributed users. If 90% of your traffic comes from Germany, your database belongs in Frankfurt, full stop. Edge is a solution to a problem geography creates, not a blanket performance upgrade.

References