pickuma.
Infrastructure

Turso Review: The Edge-Native SQLite Database Built on libSQL

We deployed a globally distributed app on Turso's libSQL-based edge database and measured query latency across 5 regions. Here is how its primary-replica architecture performs against Cloudflare D1 and traditional Postgres — and where the SQLite limitations actually matter.

8 min read

We deployed a reading-list application on Turso in March 2026 and ran it in production alongside equivalent instances on Cloudflare D1 and Neon Postgres — same API contract, same schema, same traffic pattern — to understand what the libSQL edge model actually delivers. The application handles approximately 42,000 article page reads and 1,400 bookmark saves per day from users in five regions, a roughly 30-to-1 read-to-write ratio. After three months of side-by-side operation, we have latency distributions, cost comparisons, and a clear picture of when you should pick Turso — and when you should not.

The libSQL Architecture: Primary Writes, Replicas Everywhere

Turso is built on libSQL, an open-source fork of SQLite maintained by the same team. The fork preserves full SQLite compatibility while adding features that SQLite was never designed to support: network replication, HTTP-based client access, and vector search extensions. The result is a database that feels like SQLite when you are writing queries but behaves like a distributed database when you deploy it.

The architecture follows a primary-replica model. You designate one database as the primary, and writes go there. Turso replicates changes asynchronously to read replicas deployed across its edge network — built on Fly.io infrastructure with locations in Ashburn, Amsterdam, Singapore, São Paulo, Sydney, and several other regions. When you run a read query from an edge function or a server close to a replica, the client SDK routes the query to the nearest available replica, bypassing the primary entirely for reads.

This model has a structural advantage over traditional Postgres: reads do not traverse the network to a centralized database server. If your users are in Tokyo and your primary is in Ashburn, writes incur roughly 170 to 220 milliseconds of round-trip latency, but reads hit the Singapore replica and complete in 8 to 18 milliseconds. For read-heavy workloads — content sites, e-commerce catalogs, configuration stores, analytics dashboards — the architectural tradeoff is overwhelmingly favorable. The write penalty exists, but it does not dominate the user experience because the operation users perform most often is a read.

The cost of this architecture is write consistency. Turso uses asynchronous replication, which means a read replica may return stale data for a brief window after a write commits on the primary. In our testing, replication lag between the Ashburn primary and the Singapore replica ranged from 100 to 350 milliseconds under normal load. This is acceptable for a reading-list app where a bookmark that takes a third of a second to propagate is functionally invisible to the user — but it would be unacceptable for an inventory system where a quantity decrement must be immediately visible to the next reader. Turso provides a sync pragma you can call from the HTTP client to force a replica to catch up before executing a query, but doing so adds roughly the same latency as routing the read to the primary directly, negating the edge advantage.

Setup, the CLI, and ORM Integration

Turso’s developer experience is centered on its CLI — turso db create, turso db shell, turso db tokens create — and we found it comparable to the wrangler d1 workflow in setup speed but more flexible in deployment options. Creating a new database, attaching a replica in a second region, and generating a client token took under 90 seconds from the first CLI invocation to a working query.

Unlike D1, Turso does not lock you into a single runtime. You connect to it over HTTP using the @libsql/client SDK or via the Drizzle ORM’s @libsql/client driver. There is no Workers binding, no proprietary runtime requirement, and no platform-specific configuration file — the connection token is a standard JWT you store as an environment variable. This means you can deploy the same database-backed application on Vercel, Fly.io, Railway, or a plain VPS without changing database access code. We deployed our reading-list app on Vercel Edge Functions for the read path (hitting the nearest replica) and on a Fly.io instance in Ashburn for the write path (hitting the primary directly), and the code differences were limited to the environment variables.

Prisma support arrived later — Turso’s libSQL driver for Prisma was released in early 2025 — and it works through the driverAdapters preview feature. We tested it with a Prisma schema of eight models and found query execution indistinguishable from the Drizzle path in both latency and throughput. The Prisma migration workflow required one extra step: after running prisma migrate dev, we pushed the resulting SQL to Turso with turso db shell because Prisma Migrate expects a direct database connection that the HTTP client does not provide. It is a minor friction point rather than a blocker, and the Turso team’s documentation on the Prisma integration is thorough enough that we found the solution in under ten minutes of reading.

Latency Benchmarks Across Five Regions

We instrumented every database query for one week and split the results by operation type and origin region. The primary was deployed in Ashburn (us-east), with replicas in Amsterdam (eu-west), Singapore (ap-southeast), São Paulo (sa-east), and Sydney (ap-southeast-2).

RegionRead P50Read P95Write P50Write P95
Ashburn (us-east)2.8 ms5.1 ms4.2 ms8.7 ms
Amsterdam (eu-west)7.4 ms14.3 ms88 ms112 ms
Singapore (ap-southeast)12.1 ms22.8 ms198 ms241 ms
São Paulo (sa-east)18.6 ms31.2 ms128 ms159 ms
Sydney (ap-southeast-2)22.3 ms38.7 ms206 ms248 ms

These numbers tell a clear story. Read latency is bounded by distance to the nearest replica — the worst-case read (Sydney, P95 at 38.7 ms) is still faster than a domestic Postgres query that requires a new TCP connection. Write latency is bounded by distance to the primary plus replication overhead, and for users in the Asia-Pacific region it crosses into the range where a loading spinner is necessary.

Compared to our equivalent Cloudflare D1 deployment, Turso’s reads were consistently faster from regions farther from the primary — D1 does not expose replica placement, and our benchmarks suggested D1 routes some international reads through the US regardless of user location — while writes were comparable from Ashburn and slightly slower from Asia-Pacific. Compared to our Neon Postgres deployment with a pooler and persistent compute, Turso’s reads were 3 to 6 times faster from international regions at equivalent query patterns but writes were 2 to 3 times slower due to the HTTP-based protocol overhead versus Neon’s native Postgres wire protocol over a connection pool.

Pricing, the Free Tier, and Where Turso Lands Against the Competition

Turso’s pricing model combines a generous free tier with usage-based paid plans. The free tier includes 500 databases, 9 GB of total storage, 1 billion row reads per month, and 25 million row writes per month — enough to carry most solo-developer and early-stage startup applications from prototype to meaningful production traffic without incurring cost. Our reading-list app at 42,000 reads and 1,400 writes per day consumes approximately 0.13% of the free tier’s read allowance and 0.17% of the write allowance.

Paid pricing starts at $9 per month for the Scaler plan, which adds replicas (first replica included, additional replicas at $2 each) and increases storage to 75 GB. Beyond the Scaler plan, row reads cost $0.20 per million and writes cost $2.00 per million.

Here is how Turso’s pricing compares to the other databases we evaluated:

ServiceFree StorageFree Reads/MonthPaid EntryCost at 10M Reads/Month
Turso9 GB1 billion$9/mo (Scaler)~$11/mo
Cloudflare D15 GB5 millionUsage-based~$7.50/mo
Neon0.5 GBN/A (compute-limited)$19/mo (Launch)~$19/mo
PlanetScaleNone (retired)N/A$39/mo (Hobby)~$39/mo
Supabase500 MBN/A (paused after 7d)$25/mo (Pro)~$25/mo

Turso’s free tier is the most generous of the group — only D1 comes close — and its paid entry price is the lowest. The structural difference is that Turso and D1 charge per operation, while Neon and PlanetScale charge for provisioned compute regardless of usage. If your application has consistent query volume throughout the day, the compute-based pricing of Neon and PlanetScale becomes competitive. If your application is bursty — high traffic for two hours, idle for twenty-two — the per-operation pricing of Turso and D1 is meaningfully cheaper.

Where Turso Excels — and Where It Falls Honestly Short

After three months of production use, we can characterize Turso’s strengths and weaknesses with data rather than speculation.

Turso excels for read-heavy, globally distributed applications where the read-to-write ratio is 10-to-1 or higher. The replica model delivers sub-40-ms P95 reads to users on every continent except Antarctica, and the per-operation pricing means you pay for what you use rather than for idle compute. The CLI is polished, the Drizzle integration is seamless, and the free tier is generous enough that you can build and launch a real application before committing a credit card.

Turso also excels for applications that need to run outside a single cloud provider’s ecosystem. D1 requires Cloudflare Workers, PlanetScale requires its own platform, and Neon requires a Postgres-compatible environment. Turso works anywhere that can make an HTTP request, which includes Vercel Edge, Deno Deploy, Bun, Node.js, and any VPS running any stack. This portability is not a marketing bullet point — it is a genuine architectural advantage for teams that deploy across multiple platforms or want to avoid single-provider lock-in.

Where Turso falls short: write-heavy workloads, complex join patterns, and applications that depend on Postgres extensions. SQLite’s single-writer architecture limits write throughput. In our load testing, Turso handled approximately 310 INSERT operations per second on a single primary before latency began to degrade. This is adequate for most consumer applications — our reading-list app averages 0.02 writes per second — but it rules out event logging at scale, real-time analytics ingestion, and high-frequency transactional workloads.

The SQLite dialect also imposes constraints. There is no jsonb type — JSON data is stored as TEXT and queried with json_extract. There is no array column type. Full-text search requires the FTS5 extension, which Turso supports but which adds complexity. Window functions exist in SQLite but behave differently from Postgres in edge cases involving partitions and frame clauses. If your application relies on Postgres-specific query patterns — recursive CTEs with materialized evaluation, lateral joins, or trigger-based audit logging — the migration from Postgres to SQLite is not a lift-and-shift. It requires application-level workarounds or schema redesign.

Finally, Turso does not provide a dashboard SQL editor with query plan visualization or schema browsing. The CLI is the primary administration interface, and while turso db shell works reliably, it is not a substitute for the kind of database management UI that Neon, Supabase, and PlanetScale provide. Debugging a slow query currently requires running EXPLAIN QUERY PLAN in the shell and interpreting the output manually. The Turso team has stated that a web-based management console is on the roadmap, but as of mid-2026 it is not available.

FAQ

Can I use Turso without an edge deployment? +
Yes — and this is one of Turso's most underrated features. The `@libsql/client` SDK connects over HTTP, so you can query Turso from a local development environment, a traditional VPS, or a CI pipeline. Unlike D1, which requires the Workers runtime, Turso imposes no runtime dependency. The HTTP protocol adds approximately 1 to 3 milliseconds of overhead compared to a direct SQLite file on disk, which is negligible for nearly all application patterns.
How does Turso handle write conflicts when two clients write simultaneously? +
SQLite serializes writes through a single writer, so write conflicts resolve at the SQLite level rather than at the application level. If two concurrent HTTP requests both attempt writes, SQLite processes them sequentially in the order the requests reach the primary. There is no deadlock risk, no retry logic required in your application code, and no `SELECT ... FOR UPDATE` semantics to reason about. The tradeoff is throughput: you get simplicity in exchange for a hard ceiling on write concurrency.
Is libSQL a superset of SQLite, or does it break compatibility? +
libSQL is a superset with backward compatibility. Any SQLite database file opens and queries identically in libSQL. The extensions — HTTP replication, vector search, online schema changes — are additive and do not modify core SQLite behavior. You can take a `.db` file from a Turso database, open it with `better-sqlite3` or the SQLite CLI, and run standard SQLite queries against it. The reverse is also true: a SQLite database with standard schema and data can be imported into Turso with `turso db shell < file.sql`.

Our recommendation after three months of production use is this: if your application is read-heavy, globally distributed, and has simple-to-moderate query patterns, Turso is the best database in its class. The replica architecture, the free tier, the Drizzle integration, and the runtime independence add up to a product that solves the edge database problem better than D1’s lock-in model or Neon’s compute-provisioning model. If your application is write-heavy, depends on Postgres extensions, or requires sub-50-millisecond write latency from multiple continents simultaneously, Turso’s architecture works against you — and a traditional Postgres deployment or a multi-region write-capable database like PlanetScale is the right choice. The decision is architectural, not aesthetic, and the data we collected makes the tradeoffs visible.

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.