Use Turso (libSQL) with DaloyJS Turso is a distributed database built on libSQL (a fork of SQLite). The @libsql/client driver speaks HTTP and WebSocket, so the same DaloyJS app works on Node, Bun, Deno, Cloudflare Workers, and Vercel.
One client, two connection modes@libsql/client createClient(...) HTTP and WebSocket
node / bun Embedded replica url: file:local.db + syncUrl · local reads, writes to primary
workers / edge Remote HTTP client url + authToken · no embedded replicas
The same createClient() driver serves both modes. Use an embedded replica on Node or Bun for ultra-low-latency local reads, and the remote HTTP client on Cloudflare Workers or Vercel. 1. Provision Create a database via the Turso CLI or dashboard, then grab the URL and auth token. Set them as TURSO_DATABASE_URL and TURSO_AUTH_TOKEN.
2. Install 3. Create a Turso plugin // src/db/turso.ts
import { createClient, type Client } from "@libsql/client" ;
import type { App } from "@daloyjs/core" ;
export const db : Client = createClient ({
url: process.env. TURSO_DATABASE_URL ! ,
authToken: process.env. TURSO_AUTH_TOKEN ,
});
export const tursoPlugin = {
name: "turso" ,
async register ( app : App ) {
app. decorate ( "db" , db);
app. onClose ( async () => {
db. close ();
});
},
}; 4. Augment app state // src/types/state.d.ts
import type { Client } from "@libsql/client" ;
declare module "@daloyjs/core" {
interface AppState {
db : Client ;
}
} 5. Use it in a route import { z } from "zod" ;
import { App, secureHeaders } from "@daloyjs/core" ;
import { tursoPlugin } from "./db/turso" ;
const app = new App ();
app. use ( secureHeaders ());
app. register (tursoPlugin);
const TodoSchema = z. object ({ id: z. number (), title: z. string (), done: z. boolean () });
app. route ({
method: "GET" ,
path: "/todos" ,
operationId: "listTodos" ,
responses: { 200 : { description: "ok" , body: z. array (TodoSchema) } },
handler : async ({ state }) => {
const result = await state.db. execute ( "select id, title, done from todos" );
const rows = result.rows. map (( r ) => ({
id: Number (r.id),
title: String (r.title),
done: Boolean (r.done),
}));
return { status: 200 , body: rows };
},
}); Embedded replicas (Node, Bun) For ultra-low-latency reads, use an embedded replica that syncs with the primary in the background. Writes still go to the primary; reads are local.
import { createClient } from "@libsql/client" ;
export const db = createClient ({
url: "file:local.db" ,
syncUrl: process.env. TURSO_DATABASE_URL ! ,
authToken: process.env. TURSO_AUTH_TOKEN ,
syncInterval: 60 ,
}); Cloudflare Workers / Vercel Use the standard HTTP client (no embedded replicas in Workers). Pass env.TURSO_DATABASE_URL instead of process.env.
With Drizzle ORM pnpm add drizzle - orm
// src/db/drizzle.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 }); With Prisma Prisma supports Turso through the libSQL Driver Adapter in preview. Use Drizzle if you want a stable, production-ready setup today.
See also Cloudflare D1 for a SQLite-style option that's bundled into Workers, or the database hosting overview .