Skip to content

Prisma adapter

Prisma 7 connects to every database through a driver adapter. @persql/prisma is that adapter for PerSQL: your Prisma schema and queries stay the same, and the database behind them becomes an isolated SQLite database you can provision per app, per tenant, or per agent.

npm install @persql/prisma @persql/sdk @prisma/client

Use provider = "sqlite" in schema.prisma, then:

import { PrismaClient } from "./generated/prisma/client";
import { PerSQL } from "@persql/sdk";
import { PrismaPerSQL } from "@persql/prisma";
const client = new PerSQL({ token: process.env.PERSQL_TOKEN });
const adapter = new PrismaPerSQL({ database: client.database("acme/app") });
const prisma = new PrismaClient({ adapter });
const user = await prisma.user.create({ data: { email: "[email protected]" } });
const users = await prisma.user.findMany();

Generate migration SQL with prisma migrate diff and apply it with prisma db execute --file (which runs through the adapter), or use PerSQL’s own migration tools. prisma migrate dev needs a shadow database for its schema diffing — pass one explicitly; a schema-only PerSQL branch of the main database is a natural fit:

const adapter = new PrismaPerSQL({
database: client.database("acme/app"),
shadowDatabase: client.database("acme/app-shadow"),
});

PerSQL’s HTTP API has no held connection, so prisma.$transaction(...) runs its statements individually — the same documented trade-off as Prisma’s Cloudflare D1 adapter. The adapter warns once per process when a transaction starts. When you need an atomic multi-statement write, drop to the SDK:

await client.database("acme/app").batch(
[
{ sql: "UPDATE accounts SET balance = balance - 10 WHERE id = ?", params: [1] },
{ sql: "UPDATE accounts SET balance = balance + 10 WHERE id = ?", params: [2] },
],
{ transaction: true }
);
  • Bytes columns are not supported — the wire format is JSON. Store binary data base64-encoded in a String column.
  • Affected-row counts and lastInsertId come from SQLite’s changes() and last_insert_rowid(), which PerSQL reports per write statement.
const adapter = new PrismaPerSQL({
database: new PerSQL({ local: ":memory:" }).database("test/db"),
});

Runs the same adapter against in-process SQLite — no network, no token.