Current limitations
- Certification is tuple-, revision-, and evidence-specific. The runtime and driver support matrix is the canonical evidence source and records the exact database/driver/profile/runtime/capability tuple with 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. Passing CI does not authorize publication.
db.all()is materialized. It returns a readonly array and uses O(row-count) application memory. Usedb.stream()when bounded application memory matters.- Routine streaming is not included. Materialized
db.call()consumes and closes routine resources before mapping; raw cursors, portals, requests, and carrier rows never escape. - MySQL and MariaDB prepared CALL OUT/INOUT is unsupported. Neither mysql2 3.x nor MariaDB Connector/Node.js exposes a proven public discriminator for prepared call OUT carriers, so SQLBraid does not guess a carrier row.
- PostgreSQL refcursor calls require an existing transaction. A refcursor is a transaction-bound portal, not an independent ResultSet; SQLBraid does not create a hidden transaction.
- SQL Server cursor output is not an application cursor.
CURSOR VARYING OUTPUTis not exposed as a bindable client ResultSet; emittedSELECTrows remain ordinary result sets. - SQLite routine calls are unsupported. Scalar/aggregate/window functions and virtual-table extensions remain ordinary SQL. D1 additionally has no callback transaction or incremental cursor.
- DML-returning is materialized. Use
sql.rowswithdb.execute,db.all,db.one, ordb.maybeOne. Do not infer thatRETURNING/OUTPUTis streamable across drivers. db.bulk()is command-only. It locks one DML shape, validates all inputs before I/O, uses one lease, and reports the actual mode. Root bulk has no portable atomicity or auto-chunking promise; usedb.tx()for atomicity.- Sessions and transactions are physical-scope APIs.
db.session()pins one provider lease; nested session/transaction work reuses it. Root escape and closed/sibling handles reject. Missing primitives useBRAID_SESSION_UNSUPPORTEDorBRAID_TX_UNSUPPORTED. - Transaction options are fixed and capability-driven. Isolation is one of
read-uncommitted,read-committed,repeatable-read, orserializable;readOnlyis separate. Malformed runtime values fail before acquisition withTypeError/BRAID_TX_OPTIONS_INVALID; valid but unsupported values useBRAID_TX_OPTION_UNSUPPORTED; nested explicit options useBRAID_TX_OPTIONS_NESTED. - Cancellation is capability-driven. An already-aborted signal preserves its
reason. An active signal without physical cancellation fails before I/O withUnsupportedFeatureError/BRAID_CANCEL_UNSUPPORTED; stopping iteration alone is not cancellation. - No universal input codec. Ordinary interpolation is driver-bound; application JSON, temporal, custom-class, and binary conventions remain driver/application concerns.
- Numeric fidelity is profile-specific. Exact database integers and decimals are canonical strings; approximate IEEE values are numbers.
decodeExactIntegeris an opt-in application transform. Bun 1.3.14 uses{ bigint: true }for PostgreSQL/MySQL/MariaDB and{ safeIntegers: true }for SQLite. IntegralNumberrows reject; PostgreSQL decimal is text, MySQL/MariaDB DECIMAL and binary byte carriers reject without authored SQL text/hex conversion, and SQLite native decimal is unsupported. D1 remains guarded to its safe-integer range; use authoredCAST(... AS TEXT)when exact text matters. - JSON and temporal fidelity are separate profiles. Parsed JSON may contain rounded nested numbers; native
Datemay lose fractional precision or offset/zone semantics. Use a tested text profile or authoredJSON_SERIALIZE/TO_CHAR/CONVERTSQL. - Containers are not scalar guarantees. Arrays, domains, ranges, multiranges, composites, Oracle objects/collections, SQL Server
sql_variant, vectors, and nested values remain unclassified or unsupported until tested. - Profile and codegen must agree. Changing driver JSON/temporal/numeric options creates a different evidence profile; runtime and generated models must reuse its TypePolicy.
- Bun SQL is user-selected.
createBunSqlDatabaserequiresdialect: "postgres" | "mysql" | "mariadb" | "sqlite"; the adapter does not auto-detect. Bun 1.3.14 active cancellation fails withBRAID_CANCEL_UNSUPPORTED, and stream/routine carriers fail explicitly withBRAID_STREAM_UNSUPPORTEDandBRAID_CALL_UNSUPPORTED.result.rows/result.commandmetadata is guarded bybun-sql.result-kind-metadata; for MySQL/MariaDB, emptySELECTand zero-affected DML/DDL fail after execution withBRAID_RESULT_KIND_AMBIGUOUS, so side effects may already have occurred. - Deno reuses existing adapters. A public Node-compatible driver path may work in Deno; this does not create a Deno dialect or promote a support tuple.
- No SQL-to-TypeScript inference. Arbitrary SELECT/JOIN result inference and relation graph hydration are outside the contract.
- No observer mutation/retry/routing. Observers inspect or fail an operation but cannot rewrite SQL, change binds, retry, or route.
- Metadata is evidence, not invalidity proof. Missing objects are open-world and routine argument lists may be incomplete.
- Custom drivers are not release support. Implement
QueryExecutor/ConnectionProviderand provide independent exact evidence. - Tooling is Node-first. Compiler, CLI, LSP, metadata/codegen, and Vite integration have separate build/runtime concerns; do not ship Node-only drivers into browser bundles.
These are intentional boundaries, not hidden fallback behavior. See routine calls, streaming, transactions, and the support matrix.