| name | turso |
| description | Turso: embedded SQLite for the edge — database setup, LibSQL client, schema design, multi-tenancy patterns, and deployment with Cloudflare Workers and Bun |
Turso Skill
When to activate
- Building an edge or serverless application that needs a database
- Setting up SQLite for a Cloudflare Workers or Bun-based project
- Implementing per-tenant databases (one SQLite per customer)
- Migrating from Planetscale or similar and need edge-compatible SQL
- Building with the T3 stack or similar and want a free, fast database
When NOT to use
- Complex relational data requiring joins across many tables — consider PostgreSQL
- High-write-throughput applications (SQLite has write serialization)
- Applications needing full PostgreSQL extensions (pgvector, etc.) — use Neon
Instructions
Setup
curl -sSfL https://get.tur.so/install.sh | bash
turso auth login
turso db create myapp-db
turso db create myapp-db --location fra
turso db show myapp-db
turso db tokens create myapp-db
npm install @libsql/client
npm install drizzle-orm @libsql/client
npm install -D drizzle-kit
Client setup
Set up the LibSQL client for [project type].
Project: [Cloudflare Workers / Bun / Node.js / Next.js]
import { createClient } from '@libsql/client'
export const db = createClient({
url: process.env.TURSO_DATABASE_URL!,
authToken: process.env.TURSO_AUTH_TOKEN!,
})
const result = await db.execute('SELECT * FROM users WHERE id = ?', [userId])
const users = result.rows
await db.batch([
{ sql: 'INSERT INTO orders (user_id, total) VALUES (?, ?)', args: [userId, total] },
{ sql: 'UPDATE users SET order_count = order_count + 1 WHERE id = ?', args: [userId] },
])
import { drizzle } from 'drizzle-orm/libsql'
export const db = drizzle(
createClient({
url: process.env.TURSO_DATABASE_URL!,
authToken: process.env.TURSO_AUTH_TOKEN!,
})
)
Schema with Drizzle
Define a Drizzle schema for Turso (LibSQL/SQLite dialect).
import { sqliteTable, text, integer, real } from 'drizzle-orm/sqlite-core'
import { sql } from 'drizzle-orm'
export const users = sqliteTable('users', {
id: text('id').primaryKey().$defaultFn(() => crypto.randomUUID()),
email: text('email').notNull().unique(),
name: text('name').notNull(),
plan: text('plan', { enum: ['free', 'pro', 'enterprise'] }).default('free'),
createdAt: text('created_at').default(sql`(CURRENT_TIMESTAMP)`),
})
export const posts = sqliteTable('posts', {
id: text().().$defaultFn( crypto.()),
: ().().( users., { : }),
: ().(),
: (),
: (),
: ().(sql),
})
{ }
{
: ,
: ,
: ,
: {
: process..!,
: process..!,
},
}
npx drizzle-kit generate
npx drizzle-kit migrate
Multi-tenancy pattern
Implement per-tenant database isolation with Turso.
Use case: SaaS with one SQLite database per customer (complete data isolation)
import { createClient } from '@libsql/client'
import { drizzle } from 'drizzle-orm/libsql'
export async function createTenantDb(tenantId: string) {
const response = await fetch('https://api.turso.tech/v1/databases', {
method: 'POST',
headers: {
Authorization: `Bearer ${process.env.TURSO_API_TOKEN}`,
'Content-Type': 'application/json',
},
body: JSON.stringify({
name: `tenant-${tenantId}`,
group: 'production',
}),
})
const { database } = await response.json()
return database.Hostname
}
() {
(
({
: ,
: process..!,
})
)
}
() {
tenantId = req..()!
db = (tenantId)
users = db.().(usersTable)
.(users)
}
per-tenant :
- data (, compliance, customer requirement)
- backup and restore per tenant
- row-level security complexity
- tenant
Cloudflare Workers integration
Use Turso with Cloudflare Workers.
[vars]
TURSO_DATABASE_URL = "libsql://your-db-your-org.turso.io"
# Note: auth token should be a secret, not a var
# wrangler secret put TURSO_AUTH_TOKEN
import { createClient } from '@libsql/client/web'
import { drizzle } from 'drizzle-orm/libsql'
import * as schema from './db/schema'
export default {
async fetch(request: Request, env: Env): Promise<Response> {
const client = createClient({
url: env.TURSO_DATABASE_URL,
authToken: env.TURSO_AUTH_TOKEN,
})
const db = drizzle(client, { schema })
const users = await db.select().from(schema.users).limit(10)
return .(users)
}
}
{
:
:
}
Example
User: I want to build a personal project with a database. I don't want to pay for hosting. What's the simplest path?
Claude's recommendation:
Turso free tier is unbeatable for personal projects:
- 9GB storage free
- 500 databases free (one per project or per tenant)
- Edge locations globally (data close to your users)
- No credit card required
Fastest setup:
turso db create my-project
TURSO_DATABASE_URL=$(turso db show my-project --url)
TURSO_AUTH_TOKEN=$(turso db tokens create my-project)
echo "TURSO_DATABASE_URL=$TURSO_DATABASE_URL" >> .env
echo "TURSO_AUTH_TOKEN=$TURSO_AUTH_TOKEN" >> .env
npm install @libsql/client drizzle-orm
Stack recommendation for a personal project:
- Bun + Elysia (backend) or Next.js (full-stack)
- Turso + Drizzle ORM (database)
- Deployed on Railway or Fly.io
Total cost: $0/month for most personal projects.