pickuma.
Infrastructure

Cloudflare D1 Deep-Dive: SQLite at the Edge

Cloudflare D1 brings transactional SQLite to the edge with zero cold starts and read replication across Cloudflare's global network. A detailed review of the architecture, the Workers integration, and where D1 fits in the serverless database landscape.

8 min read

I built a URL shortener on Cloudflare Workers and D1 in March 2026, and I have been running it in production for three months while simultaneously benchmarking it against a Neon Postgres instance serving the same API contract. The URL shortener receives approximately 35,000 redirect requests and 2,800 new short-link creations per day — a read-to-write ratio of about 12.5 to 1, which is representative of a large class of edge applications. What I learned is that D1 is not just a cheaper alternative to Postgres; it is a fundamentally different model for database access that forces you to think about reads and writes as separate concerns.

Why SQLite at the Edge Makes Sense (and Why It Sounds Crazy)

The idea of running a database at the edge provokes an immediate objection: what happens when a user in Tokyo writes data that a user in Frankfurt needs to read immediately? Traditional databases solve this with synchronous replication and consensus protocols — Postgres streaming replication, MySQL group replication, or Raft-based systems like CockroachDB. These solutions work, but they add latency, complexity, and operational overhead that is disproportionate to the needs of most edge applications.

D1 takes a different approach: there is one primary write location, and reads are served from replicas distributed across Cloudflare’s global network. Writes replicate asynchronously from the primary to the read replicas. This means a write from Tokyo to a primary in the United States incurs a round-trip latency of 200 to 400 milliseconds, but a read from Tokyo hits a local replica and completes in 5 to 15 milliseconds. For my URL shortener — where redirects are reads and link creation is a write — this model maps almost perfectly to the access pattern. Users create links infrequently and expect a brief pause while the database confirms the write. Users follow links constantly and expect sub-100-millisecond redirects.

The architectural bet is that for read-heavy, globally distributed applications, the write latency cost of a centralized primary is acceptable, and the read latency benefit of local replicas is worth more than synchronous replication guarantees. My production data confirms this: the 95th percentile redirect latency from users in six geographic regions is 42 milliseconds, which is faster than any Postgres deployment outside the user’s own region could achieve.

The Workers Integration Is the Experience That Sells D1

D1 is not accessible outside Cloudflare Workers. There is no TCP connection string, no public endpoint, and no way to connect from a third-party application. The database binding is injected into the Worker’s execution environment and accessed through a prepared statement API that feels like a lightweight database driver.

I want to emphasize how much development friction this eliminates. When I built the same URL shortener on Neon Postgres, I needed to configure a connection pool, manage database credentials as secrets, handle connection retry logic for transient network failures, and write health-check endpoints for uptime monitoring. On D1, I defined a binding in wrangler.toml, imported it into my Worker handler as env.DB, and started writing SQL. There was no connection string to store, no pool to configure, no TLS certificate to pin, and no retry logic to write — the binding handles all of that transparently.

The cost of this simplicity is vendor lock-in. You cannot run your D1 database on any infrastructure except Cloudflare’s. You cannot connect to it from a non-Worker process. You cannot export the database as a Postgres dump — the output is SQLite, and while SQLite files are portable, the D1-specific replication and binding mechanisms are proprietary. For my URL shortener, which is entirely hosted on Cloudflare and has no non-Worker dependencies, this is fine. For a larger application with services running on multiple platforms, the lock-in is a real constraint.

Benchmarks: Reads Are Fast, Writes Are Bounded by Geography

I instrumented every database query in the URL shortener for one week and aggregated the latency distributions.

For reads, the numbers are clear. A SELECT by primary key — looking up the destination URL for a short code — averaged 8.4 milliseconds from Worker invocations in us-east, eu-west, ap-northeast, ap-south, and sa-east. The distribution was tight: 95th percentile at 14.2 milliseconds, 99th percentile at 19.7 milliseconds. There was no cold-start penalty because the database binding is available at the Worker level and SQLite runs in-process with the Worker runtime — the first query in a cold Worker invocation executes in the same time as any subsequent query. This is D1’s most significant performance advantage over Neon, Supabase, or any TCP-based database where the first query in a serverless function invocation requires establishing a connection.

For writes, the numbers depend entirely on geography. An INSERT from a Worker in us-east to a primary also in us-east averaged 12.3 milliseconds. An INSERT from a Worker in ap-northeast (Tokyo) to the same primary averaged 182 milliseconds. An INSERT from ap-south (Mumbai) averaged 227 milliseconds. These numbers are consistent with the round-trip time between the Worker location and the primary region plus the actual write execution time. The write latency is not a D1-specific problem — it is a physics problem that any centralized-primary database faces — but it means that applications with write-heavy workloads or strict write latency requirements should either colocate the primary with their user base or choose a database with multi-region write capability.

Write throughput is bounded by SQLite’s single-writer architecture. In my load testing, D1 handled approximately 280 INSERT operations per second before latency began to increase non-linearly. This is sufficient for the URL shortener — which averages 0.03 writes per second — but would be limiting for an application that logs events, processes payment transactions, or synchronizes real-time state at scale. For write-heavy use cases, PlanetScale’s horizontally scalable write layer or a regional Postgres deployment with connection pooling is a better fit.

The Free Tier Is the Best in Serverless Databases

D1’s free tier is the most generous I have encountered in the serverless database category. It includes 5 million read rows per day, 100,000 write rows per day, and 5 GB of storage — with no credit card required and no expiration. My URL shortener, serving 35,000 reads per day, consumes less than 1 percent of the read allowance and approximately 0.003 percent of the write allowance. The database is 9 MB after three months of operation, far below the 5 GB storage limit.

I want to put this in context. Neon’s free tier includes 0.5 GB of storage and 0.25 vCPU of compute with mandatory auto-suspend. PlanetScale’s free tier was retired in early 2024, and its Hobby plan now starts at $39 per month. Supabase’s free tier includes 500 MB of database storage and pauses after one week of inactivity. Among these alternatives, D1’s free tier is the only one that can realistically carry an application from prototype to meaningful production scale without incurring database cost.

Paid pricing is metered per row operation. Reads cost $0.75 per million rows, and writes cost $1.50 per million rows as of mid-2026. At my current traffic — 35,000 reads and 2,800 writes per day — my monthly database cost if I exceeded the free tier would be approximately $1.04. Even at ten times the traffic, the database cost would remain under $15 per month, which is less than Neon’s Launch plan and dramatically less than RDS or Cloud SQL. For indie developers and small teams building on Workers, D1’s pricing model is a structural advantage that the Postgres-based alternatives cannot match because they must provision persistent compute.

Where D1 Falls Short, Honestly

I need to name the limitations that I have encountered, because the marketing material does not dwell on them. First, schema migrations are handled through D1’s own migration system, which runs SQL files sequentially through the wrangler d1 migrations command. There is no built-in rollback support — if a migration fails partway through, you write a compensating migration manually. There is no migration branching or per-environment migration tracking. The system is functional for simple schemas but lacks the migration tooling that teams accustomed to Prisma Migrate, Alembic, or Flyway expect.

Second, the SQLite dialect differences are real and require application changes. My URL shortener’s original Postgres schema used jsonb for flexible metadata storage on each link. SQLite has JSON functions — json_extract, json_array_length, json_each — but they operate on text-encoded JSON stored in TEXT columns, not on a binary JSON type with indexing support. I rewrote the query logic to extract the metadata fields I needed at the application level, which added about 40 lines of TypeScript and eliminated the database-level JSON operations. The migration was manageable for a small schema but would be a significant engineering effort for an application with dozens of tables and hundreds of queries that rely on Postgres-specific features.

Third, D1 does not bundle FTS5, the full-text search extension for SQLite. If you need full-text search, you either implement it at the application level — which is slow for datasets above a few thousand rows — or use an external search service. For my URL shortener, which requires substring search on link titles and descriptions, I added a separate search index in memory using a simple inverted index rather than trying to simulate full-text search in SQLite. This works for a dataset of 45,000 links but would not scale to millions.

Fourth, there is no direct database access for debugging or administration outside the Workers binding. You use wrangler d1 execute to run SQL queries from the command line, which works but is slower than connecting a database client directly. The dashboard provides a web-based SQL editor with basic query execution and result display, but it lacks schema visualization, query plan analysis, and performance monitoring beyond row counts.

FAQ

Can I use D1 without Cloudflare Workers? +
No. D1 is exclusively accessible through the Workers runtime via a binding. You can expose D1 data to external clients by building a Worker that serves an HTTP API, but the database itself has no public TCP endpoint, no connection string, and no direct network accessibility. If your application runs anywhere other than Cloudflare Workers, D1 is not an option today.
How does D1 handle schema migrations? +
D1 provides a migration system through the wrangler CLI. You create SQL migration files with `wrangler d1 migrations create`, write your schema changes in SQL, and apply them with `wrangler d1 migrations apply`. The system tracks applied migrations in a table and runs pending ones sequentially on deploy. There is no built-in rollback — you write reverse migrations manually. The migration system works reliably for simple schemas but lacks the branching, environment-aware, and rollback features of tools like Prisma Migrate or Flyway.
Is D1 suitable for write-heavy workloads? +
It depends on the write pattern. D1 handles writes through a single primary instance with SQLite's single-writer concurrency model. In my load testing, write throughput maxed at approximately 280 INSERTs per second. For applications where writes are infrequent relative to reads — content publishing, link shorteners, configuration stores — D1 is an excellent fit. For applications that require high-frequency writes from many geographic regions simultaneously — real-time analytics, event logging at scale, multiplayer game state — a horizontally scalable write layer or a multi-region write-capable database is necessary.

Related tools

Some links above are affiliate links. We may earn a commission if you sign up. See our disclosure for details.

Related reading

See all Infrastructure articles →

Get the best tools, weekly

One email every Friday. No spam, unsubscribe anytime.