Skip to content

Browser SQLite and D1

SQLBraid keeps SQLite as one dialect while separating the execution driver and runtime. Browser code uses SQLite WASM; a Worker binding uses Cloudflare D1. Neither path changes the SQLBraid query contract.

Install the SQLite package and official WASM runtime in the application that owns the browser/worker resource:

Terminal window
npm install sqlbraid @sqlite.org/sqlite-wasm

Create one direct database from the OO1-style object in the current realm:

import { createSqliteWasmDatabase, sql } from "sqlbraid/sqlite-wasm";
const db = createSqliteWasmDatabase(wasmDatabase, { sqlite3 });
const rows = await db.all(sql.rows<{ id: string }>`SELECT id FROM account`);

INTEGER storage is exposed as a canonical decimal string. The WASM adapter uses native column types and sqlite3_column_int64, not a numeric-value heuristic; integral REAL values remain number. Native bigint is an internal transport detail and is not a public integer mode. D1 is a separate guarded profile: safe integral JavaScript Numbers become strings, while values outside the safe range are unsupported rather than rounded.

The adapter supports prepare/bind/step/finalize, row streaming by pull, callback transactions, and command-only bulk with one prepared statement reset per item. It is a direct resource, not a pool. While a transaction or stream owns it, conflicting root operations reject; SQLBraid does not depend on an incomplete async-context polyfill.

D1 remains SQLite and uses a structural binding interface, so the package does not require a Cloudflare type package at runtime:

import { createD1Database } from "sqlbraid/d1";
const db = createD1Database(env.DB);

D1 exposes untyped JavaScript numbers. Its guarded profile rejects integral numbers outside the safe range; this also excludes integral REAL values outside that range because the public result API cannot distinguish them from rounded INTEGER values. It does not promise full int64 or exact decimal output. The API denies sqlite_version(), so db.environment() leaves the server version unknown. A Worker compatibility date is not a database version.

D1 uses ordered ?1, ?2, … binds and public result metadata for materialized queries. db.bulk() maps one logical shape to one D1Database.batch() call and reports remote-batch. D1 has no incremental row cursor in the Worker Binding API: db.stream() is BRAID_STREAM_UNSUPPORTED, and SQLBraid does not paginate to simulate streaming. Callback db.tx() is unsupported unless a future D1 primitive matches SQLBraid’s callback transaction contract.

The native D1 batch may have stronger transaction behavior than root bulk, but that is not the portable SQLBraid contract. Root bulk is not implicitly transactional and has no portable auto-chunking promise.

The runtime and driver support matrix records labels for the exact database/driver/profile/runtime/capability tuple and its revision and workflow evidence. A neighboring version or package installation is not certification. Final exact-SHA Runtime, Docs, and Release gates and explicit release authorization remain separate requirements. D1 remains Compatible; its managed SQLite version is unreported. No browser gate claims OPFS persistence, SharedArrayBuffer, remote production support, or npm publication.

Browser and Worker representation profiles

Section titled “Browser and Worker representation profiles”

SQLite remains the dialect, but WASM and D1 are different drivers and must not share an evidence label.

Driver Driver raw / SQLBraid canonical boundary Stream/bulk/transaction
SQLite WASM OO1 SQLite dynamic values; INTEGER storage is canonical string pull iteration, prepared-loop bulk, callback transaction
Cloudflare D1 binding materialized rows and ordered ?1, ?2, … binds native batch() bulk; streaming and callback transaction are unsupported

JSON1 is text unless the selected WASM build/parser proves another representation. BLOB values remain bytes. Native RETURNING is materialized before delivery. Browser SQL is sent through transparently; this does not make the browser runtime a SQL grammar implementation or make Node-only adapters browser-compatible.