Turso (SQLite на Edge) для веб-приложення
Turso — розподілена база даних на базі libSQL (форк SQLite), що працює на edge nodes по всьому світу. Запити виконуються на найближчому вузлі до користувача, latency < 10ms для read-heavy програм. Embedded replicas дозволяють запускати копію бази прямо в пам'яті програми.
Архітектура
Turso використовує модель primary + replicas:
- Primary — основна база, всі записи сюди
- Replicas — read-only копії на edge (Frankfurt, Singapore, São Paulo тощо)
- Embedded Replica — локальна копія SQLite в пам'яті Cloudflare Worker/Node.js процесу
Для глобальних read-heavy програм (<5% writes) embedded replica дає ~0ms latency на чтение — запит не виходить з runtime.
Налаштування
# CLI
turso auth login
turso db create myapp --location ams # primary у Амстердамі
# Додаткові реплики
turso db replicate myapp --location sin # Singapore
turso db replicate myapp --location gru # São Paulo
# Отримати URL та токен
turso db show myapp --url
turso db tokens create myapp
// .env
TURSO_DATABASE_URL="libsql://myapp-org.turso.io"
TURSO_AUTH_TOKEN="eyJhbGciOiJFZERTQSJ9..."
libSQL клієнт
import { createClient } from '@libsql/client';
const db = createClient({
url: process.env.TURSO_DATABASE_URL!,
authToken: process.env.TURSO_AUTH_TOKEN!,
});
// Запити — async/await
const result = await db.execute('SELECT * FROM articles WHERE published = 1 LIMIT 10');
console.log(result.rows);
// Параметризовані запити
const post = await db.execute({
sql: 'SELECT * FROM articles WHERE slug = ?',
args: [slug],
});
// Транзакції
const tx = await db.transaction('write');
await tx.execute('INSERT INTO articles (title, body) VALUES (?, ?)', ['Hello', 'World']);
await tx.execute('INSERT INTO tags (article_id, name) VALUES (?, ?)', [1, 'news']);
await tx.commit();
Embedded Replica для zero-latency чтения
import { createClient } from '@libsql/client';
import { resolve } from 'path';
const db = createClient({
url: process.env.TURSO_DATABASE_URL!,
authToken: process.env.TURSO_AUTH_TOKEN!,
syncUrl: process.env.TURSO_DATABASE_URL!,
syncInterval: 60, // секунди — як часто підтягувати зміни
});
// Перший виклик — синхронізує реплику
await db.sync();
// Усі SELECT тепер з локального SQLite — 0ms
const posts = await db.execute('SELECT id, title FROM articles');
Embedded replica особливо ефективна для SSR на Cloudflare Workers: сторінка рендерується без мережевих запитів до бази.
Drizzle ORM + Turso
npm install drizzle-orm @libsql/client
npm install -D drizzle-kit
// db/schema.ts
import { sqliteTable, text, integer } from 'drizzle-orm/sqlite-core';
export const articles = sqliteTable('articles', {
id: integer('id').primaryKey({ autoIncrement: true }),
title: text('title').notNull(),
slug: text('slug').notNull().unique(),
body: text('body'),
publishedAt: integer('published_at', { mode: 'timestamp' }),
});
// db/client.ts
import { drizzle } from 'drizzle-orm/libsql';
import { createClient } from '@libsql/client';
const client = createClient({
url: process.env.TURSO_DATABASE_URL!,
authToken: process.env.TURSO_AUTH_TOKEN!,
});
export const db = drizzle(client);
// Запити
const posts = await db.select().from(articles)
.where(isNotNull(articles.publishedAt))
.orderBy(desc(articles.publishedAt))
.limit(10);
Multi-tenancy з Turso
Turso підтримує бази даних per tenant:
// Створити БД для кожного tenant через API
async function provisionTenantDB(tenantSlug: string) {
const response = await fetch(`https://api.turso.tech/v1/organizations/${ORG}/databases`, {
method: 'POST',
headers: {
'Authorization': `Bearer ${TURSO_API_TOKEN}`,
'Content-Type': 'application/json',
},
body: JSON.stringify({
name: `tenant-${tenantSlug}`,
group: 'default',
}),
});
const { database } = await response.json();
// Створити токен доступу для tenant
const tokenRes = await fetch(
`https://api.turso.tech/v1/organizations/${ORG}/databases/${database.Name}/auth/tokens`,
{ method: 'POST', headers: { Authorization: `Bearer ${TURSO_API_TOKEN}` } }
);
const { jwt } = await tokenRes.json();
return { url: `libsql://${database.Name}-${ORG}.turso.io`, token: jwt };
}
До 10 000 баз на одному аккаунті — жизнеспособна модель для micro-SaaS.
Коли вибирати Turso
Підходить:
- Read-heavy глобальні програми (< 5% writes)
- Cloudflare Workers / Deno Deploy (немає TCP, потрібен HTTP)
- Micro-SaaS з database-per-tenant на SQLite
- Програми з простою схемою без складних JOIN
Не підходить:
- Write-heavy нагрузки (всі записи йдуть у primary — немає sharding)
- Складні аналітичні запити (SQLite не ClickHouse)
- Вимоги до PostgreSQL-специфічних можливостей (RLS, advanced types, PostGIS)
- ACID транзакції на кількох таблицях з високим паралелізмом
Графік
Налаштування Turso, libSQL клієнт + Drizzle ORM, embedded replica для Cloudflare Workers, CI міграції: 1–2 дні.







