Claude Code for Turso Database — Workflow Guide
The Setup
You are using Turso, the edge-hosted SQLite database powered by libSQL. Turso replicates your database to edge locations worldwide for low-latency reads, while maintaining a primary location for writes. Claude Code can write Turso queries and schema, but it generates PostgreSQL patterns and misses the embedded replica model.
What Claude Code Gets Wrong By Default
-
Uses PostgreSQL connection strings. Claude writes
postgresql://connection URLs. Turso useslibsql://protocol with auth tokens:libsql://your-db.turso.io?authToken=.... -
Writes PostgreSQL-specific SQL. Claude uses
SERIAL,RETURNING *, and PostgreSQL functions. Turso runs libSQL (SQLite-compatible) — useINTEGER PRIMARY KEY AUTOINCREMENT,RETURNING(supported), and SQLite-compatible functions. -
Creates connection pools. Claude sets up pg-pool or connection pooling. Turso’s libSQL client is HTTP-based — each request is independent, no connection pooling needed or supported.
-
Ignores embedded replicas. Claude always queries the remote database. Turso supports embedded replicas that sync to a local SQLite file, enabling zero-latency reads from a local database with automatic sync.
The CLAUDE.md Configuration
# Turso Edge Database Project
## Database
- Platform: Turso (edge SQLite, libSQL protocol)
- Client: @libsql/client
- ORM: Drizzle with libSQL driver
- Replicas: embedded local replicas for edge reads
## Turso Rules
- Connection: createClient({ url: 'libsql://...', authToken: '...' })
- SQL dialect: SQLite-compatible (libSQL extensions available)
- Embedded replica: syncUrl for remote, url for local file
- Sync: client.sync() to pull latest from primary
- Schema: SQLite types (TEXT, INTEGER, REAL, BLOB)
- Migrations: Drizzle Kit with libSQL driver
- No connection pooling — HTTP-based stateless client
## Conventions
- Client singleton in lib/turso.ts
- TURSO_DATABASE_URL and TURSO_AUTH_TOKEN in env
- Embedded replica for serverless edge functions
- Sync before reads for consistency-critical operations
- Use Drizzle ORM for type-safe queries
- Migrations via drizzle-kit push or generate
- Group name for multi-database setups
Workflow Example
You want to set up Turso with Drizzle ORM and embedded replicas. Prompt Claude Code:
“Configure Turso with Drizzle ORM for a Next.js project. Set up an embedded replica for edge function reads, define a users table schema, generate the migration, and write a query function with automatic sync.”
Claude Code should create the libSQL client with createClient({ url: 'file:local.db', syncUrl: process.env.TURSO_DATABASE_URL, authToken }), configure Drizzle with the libSQL adapter, define the users table with SQLite types, and write query functions that call client.sync() before critical reads.
Common Pitfalls
-
Using
client.sync()on every read. Claude syncs before every query. Sync is a network call — doing it on every read adds latency and defeats the purpose of the local replica. Sync periodically or before consistency-critical operations only. -
SQLite vs PostgreSQL function differences. Claude uses
NOW()orCURRENT_TIMESTAMPwith timezone. SQLite stores dates as text or integers — usedatetime('now')for current time and store consistently in UTC. -
Write path for embedded replicas. Claude writes to the local embedded replica expecting it to sync upstream. Embedded replicas are read-only locally — writes must go to the primary (remote) URL. Configure a separate client for writes pointing to the remote URL.