Skip to content

Multiple databases ​

A Worker can bind several D1 databases. Each gets its own schema file and base class, and each Model queries the database its base class names.

Binding the databases ​

Add each database to your Wrangler config, with its own migrations_dir:

jsonc
{
  "d1_databases": [
    { "binding": "DB", "database_name": "my-app-db", "database_id": "…" },
    {
      "binding": "LOGS",
      "database_name": "my-app-logs",
      "database_id": "…",
      "migrations_dir": "logs-migrations",
    },
  ],
}

Wrangler applies a folder’s migrations to one database, so each needs its own folder.

Generating a schema for each ​

Generate the schemas as usual:

sh
npx d1-record schema

With several databases, it writes one of each per binding:

BindingSchemaBase class
DBsrc/db/DB.tsDbRecord, in src/models/db-record.ts
LOGSsrc/db/LOGS.tsLogsRecord, in src/models/logs-record.ts

Each base class names its binding, so its Models query that database:

ts
import { LogsRecord } from "./logs-record";

export class Entry extends LogsRecord("entries") {}

await Entry.where({ level: "error" }).count(); // on LOGS

Generating Models for one database ​

Name the binding with --database:

sh
npx d1-record g model Entry 'level:string!' message --database LOGS
npx wrangler d1 migrations apply my-app-logs --local

Opening several for a request ​

To open a request’s databases with a Session or onQuery, pass them all to withDatabase. Each Model uses the one on its binding:

ts
import { connect, withDatabase, type Database } from "@forestfuture/d1-record";

const databases: Database[] = [connect(env.DB, { session: "first-primary" }), connect(env.LOGS)];
return withDatabase(databases, handle); // each Model uses the one on its binding

TIP

A batch writes to one database, so entries from two databases throw IncompatibleRelation.