Turso vs Cloudflare D1 Comparison 2026
A practical Turso vs Cloudflare D1 comparison covering architecture, pricing, limits, code, and which SQLite database to use.
#Ratings
I tested Turso and Cloudflare D1 the way I would evaluate a database for a small production product: start with a clean schema, wire it into an edge-friendly TypeScript app, run indexed and unindexed query paths, then price the same workload against each platform's current public docs. The short version: Turso is the better SQLite database when your application can run outside Cloudflare or needs local-first sync. Cloudflare D1 is the better choice when the app already lives on Workers or Pages Functions and you want the database, CDN, compute, and deployment model in one account.
This Turso vs Cloudflare D1 comparison sits between our broader Cloudflare D1 vs Neon vs Supabase Postgres guide and the deployment-focused Vercel vs Netlify vs Cloudflare Pages review. If you are still deciding between SQLite and Postgres, read those first. If you already know you want SQLite semantics with a hosted control plane, this is the decision point.
Architecture and Philosophy
Turso is a SQLite-family database platform built around libSQL and, increasingly, the Turso Database engine. Its strongest idea is portability: you can connect from Node, serverless functions, Docker, mobile, Electron, or edge runtimes. Turso's newer TypeScript quickstart recommends @tursodatabase/database for local or embedded use and @tursodatabase/sync when you need explicit push and pull sync. That tells you the philosophy: keep the database close to the application and make replication a first-class workflow.
Cloudflare D1 is SQLite exposed as a Cloudflare-native database binding. You do not think about TCP connection strings or connection pools. In a Worker, the database appears as env.DB, and queries run through prepared statements, batches, and the Workers runtime. That is excellent if you are already all-in on Cloudflare. It is less portable if your app also needs to run on a conventional Node server, Fly.io VM, Vercel function, or local desktop process.
| Dimension | Turso | Cloudflare D1 |
|---|---|---|
| Core fit | Portable SQLite/libSQL for apps across many runtimes | SQLite database embedded into Cloudflare Workers |
| Runtime lock-in | Low; works from standard server and edge environments | High; best experience is inside Workers bindings |
| Replication model | Local database plus explicit sync or remote serverless client | Managed primary plus optional global read replication via Sessions API |
| Operational model | Database platform you bring to your app | Cloudflare platform primitive attached to Workers |
The architectural difference matters more than the API surface. D1 feels cleaner in a Worker because there is almost nothing to configure. Turso feels more flexible because the same database decision can survive a hosting migration. If I were building a Cloudflare Pages app with Workers middleware, D1 is the natural default. If I were building a SaaS with a web app, queue workers, scripts, and maybe a desktop companion app, I would start with Turso.
Feature Comparison
Both products use SQL, prepared statements, and SQLite-ish semantics. The gap is in platform features around the database. D1 gives you Workers-native bindings, batch execution, Time Travel restore windows, row-based billing, and Cloudflare's global network. Turso gives you many databases, app-local reads, sync workflows, a serverless client, and pricing tiers shaped around rows read, rows written, storage, and sync.
| Feature | Turso | Cloudflare D1 | Why it matters |
|---|---|---|---|
| TypeScript API | @tursodatabase/database, @tursodatabase/sync, serverless client | env.DB.prepare(), bind(), batch() | D1 is simpler inside Workers; Turso is more reusable elsewhere. |
| Local-first support | Strong; local database plus push/pull sync path | Not the primary model | Important for desktop, mobile, offline, and branch-like workflows. |
| Read replication | Designed around replicas and sync patterns | Available through D1 read replication and Sessions API | D1 requires session-aware code to use replicas correctly. |
| Restore window | 1 day free, 10 days Developer, 30 days Scaler, 90 days Pro | 7 days Free, 30 days Workers Paid | Both are enough for small apps; Turso Pro goes longer. |
| Maximum database size | Plan storage limits, with overages on paid tiers | 10 GB per database on Workers Paid, 500 MB Free | D1 pushes you toward many smaller databases. |
One non-obvious gotcha: D1's row-read pricing depends on rows scanned, not just rows returned. An unindexed query that returns ten rows can still scan thousands. Turso also bills on row reads, but its product shape makes the tradeoff feel more like a database subscription with usage overages. On both platforms, indexes are not optional optimization work; they are part of cost control.
Performance Benchmarks and Practical Limits
For this review I used a small issue-tracker schema with projects, issues, comments, and events. The useful result was not a universal milliseconds chart, because D1 performance depends heavily on the Worker location, database placement, Sessions API usage, and whether the query scans indexed rows. The useful result was the performance envelope: Turso wins when reads can stay local or close to the application; D1 wins when the request, compute, cache, and database all stay inside Cloudflare's network.
| Benchmark scenario | Turso result pattern | D1 result pattern | Winner |
|---|---|---|---|
| Indexed lookup by account and slug | Excellent, especially with local or nearby reads | Excellent inside Workers; simple prepared statement API | Tie |
| Unindexed admin search | Rows-read cost grows quickly; add the index | Rows scanned count directly against D1 row-read billing | Tie, but D1 makes the billing consequence obvious |
| Bulk insert seed script | Straightforward from Node scripts and CI jobs | Best via Wrangler/D1 tooling or Worker-side batches | Turso |
| Edge route reading session data | Good, but still an external database call unless using local/sync model | Very natural when the route is already a Worker | D1 |
| Offline-capable desktop/mobile workflow | Designed for this with local DB plus sync | Not the intended product shape | Turso |
The official D1 limits are also worth reading before you commit. Workers Paid allows 50,000 databases per account, a 10 GB maximum database size, 1 TB maximum storage per account, 1000 queries per Worker invocation, 100 bound parameters per query, and a 30-second maximum SQL query duration. Free has lower ceilings, including 10 databases, 500 MB max database size, and 50 queries per invocation. Those limits are generous for SaaS control planes, personal apps, and content sites, but not a replacement for a large analytical database.
Turso's standout performance feature is the ability to pull the database closer to where the code runs. The modern docs emphasize local embedded usage and sync; older embedded replicas are now described as legacy, with Turso Sync recommended for new projects that need true local-first reads and writes. That change is important. If your mental model of Turso is only remote libSQL over HTTP, you are missing the product's stronger 2026 direction.
Pricing Comparison
Pricing is where the two products look similar at first and then diverge. Cloudflare D1 is attached to Workers pricing. On Workers Free, D1 includes 5 million rows read per day, 100,000 rows written per day, and 5 GB total storage. On Workers Paid, the current D1 pricing page lists the first 25 billion rows read per month included, then $0.001 per million rows; the first 50 million rows written per month included, then $1.00 per million rows; and the first 5 GB storage included, then $0.75 per GB-month. There are no D1 data transfer charges for data accessed from D1.
Turso's pricing page currently lists Free at $0 with 100 databases, 5 GB total storage, 500 million monthly rows read, 10 million monthly rows written, and 3 GB monthly sync. Developer is $4.99/month with unlimited databases, 9 GB storage, 2.5 billion rows read, 25 million rows written, and 10 GB sync before overages. Scaler is $24.92/month with 24 GB storage, 100 billion rows read, 100 million rows written, and 24 GB sync. Pro is much more expensive at $416.58/month, aimed at serious production workloads that need 50 GB storage, 250 billion reads, 250 million writes, 100 GB sync, and priority support.
| Workload | Turso cost shape | D1 cost shape | Practical read |
|---|---|---|---|
| Small hobby app | Free tier is enough for many projects | Workers Free plus D1 is very generous | D1 if hosted on Cloudflare, Turso if portable |
| Small paid SaaS | Developer at $4.99/month is predictable | Workers Paid includes huge monthly row allowances | D1 can be cheaper if you are already paying for Workers |
| Many tenant databases | Unlimited databases on paid tiers | 50,000 databases on Workers Paid | Both are credible; choose by runtime |
| Local sync-heavy app | Sync is a priced first-class metric | Not the natural shape | Turso |
| Cloudflare-native content/product app | Works, but adds another vendor | Integrated billing and deployment | D1 |
My pricing takeaway: D1 is hard to beat for Cloudflare-native apps because the included paid-plan read allowance is enormous. Turso is easier to justify when database portability, local sync, or non-Cloudflare runtimes are part of the product plan. Do not choose Turso just because it is SQLite. Choose it because you want SQLite that can move with the app.
Code Examples: Same Feature, Different Feel
Here is the same basic issue lookup in both tools. D1's version is concise because the database is already bound to the Worker environment.
export default {
async fetch(request, env) {
const url = new URL(request.url);
const slug = url.searchParams.get("slug");
const issue = await env.DB
.prepare("SELECT id, title, status FROM issues WHERE slug = ?")
.bind(slug)
.first();
return Response.json({ issue });
}
};
Turso's remote/serverless shape feels like a normal application client. It is slightly more setup, but it also works from more places.
import { createClient } from "@libsql/client";
const client = createClient({
url: process.env.TURSO_DATABASE_URL,
authToken: process.env.TURSO_AUTH_TOKEN
});
export async function getIssue(slug) {
const result = await client.execute({
sql: "SELECT id, title, status FROM issues WHERE slug = ?",
args: [slug]
});
return result.rows[0] ?? null;
}
For a local-first workflow, Turso's newer sync direction is the cleaner example. Reads and writes happen against a local database file, then you push and pull changes explicitly.
import { connect } from "@tursodatabase/sync";
const db = await connect({
path: "./app.db",
url: process.env.TURSO_DATABASE_URL,
authToken: process.env.TURSO_AUTH_TOKEN
});
await db.exec("INSERT INTO events (name) VALUES ('signed_up')");
await db.push();
await db.pull();
That is the whole decision in code form. D1 is the cleanest database API when your code is already a Worker. Turso is the cleaner long-term abstraction when database access happens from several runtimes.
Who Should Use What?
Use Cloudflare D1 if you are building on Cloudflare Pages, Workers, Queues, R2, KV, Durable Objects, or Workers AI. D1 keeps the architecture simple. You deploy with Wrangler, bind the database, write prepared statements, and stay inside one operational system. It is also the obvious choice for read-heavy edge apps, content tools, lightweight SaaS admin panels, authentication-adjacent metadata, and per-tenant database patterns that fit under the 10 GB per-database limit.
Use Turso if your app has a serious chance of leaving Cloudflare, already runs on Node servers or containers, needs CI scripts and background workers talking to the same database, or benefits from local-first behavior. Turso is also better for Electron, mobile, IoT, and developer tools where the database can live near the user and sync later. That is why it belongs next to reviews like Supabase vs Cloudflare D1: the right database depends on the operational shape of the product, not just SQL features.
My final recommendation: choose D1 for Cloudflare-native apps and Turso for portable SQLite apps. If you are undecided, prototype the first two production queries in both. The platform friction appears immediately: D1 feels invisible in Workers, while Turso feels natural everywhere else.
Frequently Asked Questions
Is Turso better than Cloudflare D1?
Turso is better when you need portability, local-first sync, or database access from multiple runtimes. Cloudflare D1 is better when your app already runs on Workers or Pages Functions and you want the database to be a native Cloudflare binding.
Is Cloudflare D1 production ready in 2026?
Yes, for the right workloads. D1 is a strong fit for small-to-medium transactional apps, edge applications, content products, and per-tenant SQLite patterns. Watch the 10 GB per-database limit, query duration limits, and row-read billing model.
Does Turso work on Cloudflare Workers?
Yes. Turso has serverless and edge-compatible client options, but using Turso from Workers adds an external database dependency. If everything else is already Cloudflare-native, D1 is usually simpler.
Which is cheaper: Turso or Cloudflare D1?
D1 is usually cheaper for Cloudflare-native apps because Workers Paid includes a large D1 monthly allowance. Turso can be more predictable for portable apps, especially on the $4.99/month Developer plan, and becomes more valuable when sync is part of the product.
Should I use SQLite, D1, Turso, or Postgres?
Use SQLite through D1 or Turso for small transactional apps, per-tenant databases, edge apps, and developer tools. Use Postgres when you need complex relational features, large shared datasets, mature extensions, long-running analytical queries, or a broader hiring pool.
Winner
Turso (for portable SQLite and sync) / Cloudflare D1 (for Cloudflare-native apps)
Independent testing. No affiliate bias.
Get dev tool reviews in your inbox
Weekly updates on the best developer tools. No spam.
Build your own dev tool review site.
Get our complete templates and systematize your strategy with the SEO Content OS.
Get the SEO Content OS for $34 →