Turso & libSQL Best Practices
Reference Files
| File | When to read | |------|-------------| | references/advanced-features.md | Working with embedded replicas, vector search/AI embeddings, Drizzle ORM, database branching, encryption at rest, or SQLite extensions |
Overview
Turso is a fully managed SQLite-compatible database platform built on libSQL, a fork of SQLite. It provides edge distribution, embedded replicas, native vector search, branching, and point-in-time recovery. Core principle: SQLite simplicity with cloud-scale distribution.
When to Use
- Building applications needing SQLite with cloud features
- Implementing embedded replicas for offline-first apps
- Adding vector search/AI embeddings to applications
- Setting up local development with Turso
- Managing database migrations and branching
Quick Reference
| Task | Command/Pattern |
| --------------------- | --------------------------------------------------------------------------- |
| Install CLI (macOS) | brew install tursodatabase/tap/turso |
| Install CLI (Linux) | curl -sSfL https://get.tur.so/install.sh \| bash |
| Login | turso auth login |
| Create database | turso db create my-db |
| Connect to shell | turso db shell my-db |
| Get credentials | turso db show my-db --url and turso db tokens create my-db |
| Local dev server | turso dev |
| Local with file | turso dev --db-file local.db |
Installation & Setup
CLI Installation
# macOS
brew install tursodatabase/tap/turso
# Linux / Windows (WSL)
curl -sSfL https://get.tur.so/install.sh | bash
Authentication
turso auth signup # Sign up (opens browser)
turso auth login # Login (opens browser)
turso auth login --headless # Headless mode (WSL/CI)
Create Your First Database
turso db create my-db # Auto-detects closest region
turso db show my-db # Show database info
turso db show my-db --url # Get connection URL
turso db tokens create my-db # Create auth token
turso db shell my-db # Connect to shell
SDK Usage (TypeScript/JavaScript)
Installation
npm install @libsql/client
Basic Connection
import { createClient } from '@libsql/client'
const client = createClient({
url: process.env.TURSO_DATABASE_URL!,
authToken: process.env.TURSO_AUTH_TOKEN,
})
Execute Queries
// Simple query
const result = await client.execute('SELECT * FROM users')
// Positional placeholders
const result = await client.execute({
sql: 'SELECT * FROM users WHERE id = ?',
args: [1],
})
// Named placeholders (:, @, or $)
const result = await client.execute({
sql: 'INSERT INTO users (name, email) VALUES (:name, :email)',
args: { name: 'Alice', email: 'alice@example.com' },
})
Response Structure
interface ResultSet {
rows: Array<Row> // Row data (empty for writes)
columns: Array<string> // Column names
rowsAffected: number // Affected rows (writes)
lastInsertRowid?: bigint // Last inserted row ID
}
Batch Transactions
const results = await client.batch(
[
{ sql: 'INSERT INTO users (name) VALUES (?)', args: ['Alice'] },
{ sql: 'INSERT INTO users (name) VALUES (?)', args: ['Bob'] },
],
'write' // Transaction mode: "write" | "read" | "deferred"
)
Interactive Transactions
const transaction = await client.transaction('write')
try {
const balance = await transaction.execute({
sql: 'SELECT balance FROM accounts WHERE id = ?',
args: [userId],
})
if (balance.rows[0].balance >= amount) {
await transaction.execute({
sql: 'UPDATE accounts SET balance = balance - ? WHERE id = ?',
args: [amount, userId],
})
await transaction.commit()
} else {
await transaction.rollback()
}
} catch (e) {
await transaction.rollback()
throw e
}
Transaction Modes
| Mode | SQLite Command | Description |
| ---------- | ---------------------------- | ------------------------------------------------ |
| write | BEGIN IMMEDIATE | Read/write, serialized on primary |
| read | BEGIN TRANSACTION READONLY | Read-only, can run on replicas in parallel |
| deferred | BEGIN DEFERRED | Starts as read, upgrades to write on first write |
Local Development
Option 1: SQLite File (Simplest)
const client = createClient({ url: 'file:local.db' })
Option 2: Turso Dev Server (Full Features)
turso dev # Start local libSQL server
turso dev --db-file local.db # With persistent file
const client = createClient({ url: 'http://127.0.0.1:8080' })
Environment Variables Pattern
# Production
TURSO_DATABASE_URL=libsql://my-db-org.turso.io
TURSO_AUTH_TOKEN=eyJ...
# Development
TURSO_DATABASE_URL=file:local.db
# No auth token needed
Common Mistakes
| Mistake | Fix |
| ------------------------------------------ | ------------------------------------------- |
| Using @libsql/client/web with file URLs | Use @libsql/client for local files |
| Long-running write transactions | Keep writes short, they block other writes |
| Opening local file during sync | Wait for sync to complete |
| Forgetting to sync embedded replicas | Call sync() or use syncInterval |
| Hardcoding credentials | Use environment variables |
| Not using transactions for related writes | Use batch() or transaction() |
Performance Tips
- Use
batch()for multiple related operations - Use
readtransactions for read-only queries (parallel on replicas) - Set appropriate
syncIntervalfor embedded replicas - Use vector indexes for tables with >1000 rows
- Use positional placeholders for frequently executed queries
Scan to join WeChat group