Claude Code for Turso Database — Workflow Guide

Written by Michael Lip · Solo founder of Zovo · $400K+ on Upwork · 100% JSS Join 50+ builders · More at zovo.one

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

  1. Uses PostgreSQL connection strings. Claude writes postgresql:// connection URLs. Turso uses libsql:// protocol with auth tokens: libsql://your-db.turso.io?authToken=....

  2. Writes PostgreSQL-specific SQL. Claude uses SERIAL, RETURNING *, and PostgreSQL functions. Turso runs libSQL (SQLite-compatible) — use INTEGER PRIMARY KEY AUTOINCREMENT, RETURNING (supported), and SQLite-compatible functions.

  3. 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.

  4. 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

  1. 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.

  2. SQLite vs PostgreSQL function differences. Claude uses NOW() or CURRENT_TIMESTAMP with timezone. SQLite stores dates as text or integers — use datetime('now') for current time and store consistently in UTC.

  3. 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.