Skip to content
VibORM
Esc
navigateopen⌘Jpreview
On this page

Cloudflare D1

SQLite driver for Cloudflare D1 using Worker bindings

Requirements

  • Cloudflare Workers environment (no nodejs_compat flag needed)

Configuration

import { createClient } from "viborm/d1";

export default {
  async fetch(request: Request, env: Env) {
    const client = createClient({
      database: env.DB, // D1 binding from wrangler.toml
      schema,
    });

    const users = await client.user.findMany();
    return Response.json(users);
  },
};

Options

Option Type Description
database D1Database D1 database binding from Worker env

Binary values

Blob fields bind Uint8Array values directly to D1, and D1’s byte-array results are normalized back to a plain Uint8Array — no Node Buffer or nodejs_compat flag involved.

wrangler.toml

[[d1_databases]]
binding = "DB"
database_name = "my-database"
database_id = "xxxxxxxx-xxxx-xxxx-xxxx-xxxxxxxxxxxx"

Transactions & Batching

D1 does not support traditional dynamic transactions, but VibORM provides full support for batch mode using D1’s native batch() API.

Use the array API for atomic operations - VibORM uses D1’s native batch() under the hood:

// Atomic execution using D1's native batch()
const [user, post] = await client.$transaction([
  client.user.create({ data: { name: "Alice", email: "alice@example.com" } }),
  client.post.create({ data: { title: "Hello", authorId: "preset-id" } }),
]);

Dynamic Transactions

Dynamic transactions (callback API) are unsupported and reject:

// Throws TransactionError: D1 does not support callback transactions
await client.$transaction(async (tx) => {
  const user = await tx.user.create({ data: { name: "Alice" } });
  await tx.post.create({ data: { title: "Hello", authorId: user.id } });
});

Migrations

Schema push executes atomically through D1’s native batch(). File-based migrate apply requires a callback transaction and rejects on D1 — apply migrations with wrangler d1 migrations instead.

Capabilities

Dynamic transactions reject; batch mode is fully supported via D1’s native batch(). See the feature matrix for the full comparison.

Limitations

  • Batch operations cannot read each other’s results — use a single nested write for dependent mutations
  • Only available in Cloudflare Workers
  • SQLite dialect - no LATERAL joins, limited FULL OUTER JOIN
  • JSON columns are parsed automatically
  • Boolean values stored as integers (0/1)

Was this page helpful?