Introduction
Turso is an edge-hosted SQLite database designed for modern applications. Built on LibSQL (a fork of SQLite), it offers embedded replicas for ultra-low latency and simple operation. This guide covers everything you need to get started.
Understanding Turso & LibSQL
What is LibSQL?
LibSQL is an open-source fork of SQLite that adds:
- HTTP API support
- Embedded replicas
- Better replication
- Rust bindings
What is Turso?
Turso is a managed service built on LibSQL:
- Edge locations worldwide
- Embedded replicas for edge
- Simple pricing
- Open source
graph TB
subgraph "Traditional Database"
Client1[Client]
DC1[Single Data Center]
Client1 -->|50ms+| DC1
end
subgraph "Turso + Embedded Replicas"
Client2[Client]
Edge[Edge Location]
Replica[Local Replica]
DC2[Primary DB]
Client2 -->|1ms| Edge
Edge -->|sync| Replica
Replica -->|async| DC2
end
Why Turso?
| Feature | Benefit |
|---|---|
| Edge Ready | Sub-millisecond latency |
| Embedded Replicas | Local DB on client |
| Simple | No database ops |
| Portable | Self-host anywhere |
| Open Source | LibSQL is free |
| Serverless | Pay per request |
Getting Started
Installation
# Install Turso CLI
brew install/tursodatabase/tap/turso
# Or from source
cargo install turso
# Login
turso auth login
# Create database
turso db create my-app
Connection
// Using @libsql/client
import { createClient } from '@libsql/client/web';
// Edge location (Turso)
const client = createClient({
url: 'libsql://my-app.turso.io',
authToken: process.env.TURSO_TOKEN,
});
// Local embedded replica
const localClient = createClient({
url: 'file:local.db',
});
Embedded Replicas
What are Embedded Replicas?
Embedded replicas sync Turso database locally, enabling:
- Zero-latency queries
- Offline support
- Reduced costs
// Client-side embedded replica
import { createClient } from '@libsql/client/web';
const client = createClient({
url: 'embedded:local',
authToken: process.env.TURSO_TOKEN,
});
// Automatically syncs in background
// All queries are instant!
Sync Configuration
// Fine-tune sync behavior
const client = createClient({
url: 'embedded:local',
syncUrl: 'libsql://my-app.turso.io',
authToken: process.env.TURSO_TOKEN,
syncInterval: 1000, // Sync every second
authInterval: 30000, // Re-auth every 30s
});
// Manual sync
await client.sync();
Basic Operations
Queries
// Create table
await client.execute(`
CREATE TABLE users (
id INTEGER PRIMARY KEY AUTOINCREMENT,
name TEXT NOT NULL,
email TEXT UNIQUE
)
`);
// Insert
await client.execute({
sql: 'INSERT INTO users (name, email) VALUES (?, ?)',
args: ['John', '[email protected]'],
});
// Select
const result = await client.execute('SELECT * FROM users');
// With parameters
const result = await client.execute({
sql: 'SELECT * FROM users WHERE id = ?',
args: [1],
});
Transactions
// Batch operations
const batch = await client.batch([
{ sql: 'INSERT INTO users (name) VALUES (?)', args: ['Alice'] },
{ sql: 'INSERT INTO users (name) VALUES (?)', args: ['Bob'] },
{ sql: 'UPDATE users SET name = ? WHERE name = ?', args: ['Carol', 'Alice'] },
]);
Migrations
// Simple migration script
async function migrate(client, migrations) {
// Create migrations table
await client.execute(`
CREATE TABLE IF NOT EXISTS _migrations (
id INTEGER PRIMARY KEY,
name TEXT UNIQUE,
applied_at DATETIME DEFAULT CURRENT_TIMESTAMP
)
`);
for (const migration of migrations) {
const existing = await client.execute({
sql: 'SELECT id FROM _migrations WHERE name = ?',
args: [migration.name],
});
if (!existing.rows.length) {
await client.execute(migration.sql);
await client.execute({
sql: 'INSERT INTO _migrations (name) VALUES (?)',
args: [migration.name],
});
}
}
}
Turso Platform
Database Management
# List databases
turso db list
# Show info
turso db show my-app
# Delete
turso db destroy my-app
# Create replica in region
turso db create my-app --replica us-east
Team Features
# Invite team member
turso org invite [email protected]
# List members
turso org members
Use Cases
Edge Functions
// Cloudflare Workers + Turso
export default {
async fetch(request) {
const client = createClient({
url: 'libsql://my-app.turso.io',
authToken: TURSO_TOKEN,
});
const result = await client.execute('SELECT * FROM users');
return new Response(JSON.stringify(result.rows));
}
};
Mobile Apps
// React Native - embedded replica
import { createClient } from '@libsql/client';
const client = createClient({
url: 'embedded:app.db',
syncUrl: 'libsql://my-app.turso.io',
authToken: AUTH_TOKEN,
});
// Works offline!
// Automatically syncs when online
Serverless
// Vercel Edge Functions
export const config = { runtime: 'edge' };
export default async function handler() {
const client = createClient({
url: process.env.TURSO_URL,
authToken: process.env.TURSO_TOKEN,
});
const users = await client.execute('SELECT * FROM users LIMIT 10');
return Response.json(users.rows);
}
Turso vs Others
| Feature | Turso | PlanetScale | SQLite |
|---|---|---|---|
| Type | LibSQL fork | MySQL | Original |
| Edge | โ Native | โ | โ |
| Embedded | โ | โ | โ |
| Serverless | โ | โ | Limited |
| Open Source | โ | โ | โ |
| Free Tier | 500MB | 5GB | Free |
Best Practices
1. Use Embedded Replicas
// Always prefer embedded on client
const client = createClient({
url: 'embedded:local-cache.db',
syncUrl: TURSO_URL,
authToken: TURSO_TOKEN,
});
2. Handle Conflicts
// Last-write-wins (default)
// Or implement custom conflict resolution
const client = createClient({
url: 'embedded:local',
syncUrl: TURSO_URL,
// Add conflict handler
onConflict: (local, remote) => {
// Return winner
return remote.updated_at > local.updated_at ? remote : local;
}
});
3. Index Wisely
-- Always index foreign keys
CREATE INDEX idx_posts_user ON posts(user_id);
-- Index frequently queried columns
CREATE INDEX idx_users_email ON users(email);
-- Composite index
CREATE INDEX idx_orders_status_date
ON orders(status, created_at);
Conclusion
Turso and LibSQL are perfect for:
- Edge applications needing low latency
- Serverless environments
- Mobile apps needing offline support
- Simple projectsไธๆณ็ฎก็ๅคๆๆฐๆฎๅบ
- Portability - self-host anywhere
Start with Turso’s free tier, add embedded replicas for speed.
Comments