Architecture mental model
SQLBraid is a pipeline with narrow boundaries. This is intentional.
- The SQL text stays visible.
- Values stay values.
- Adapters own the physical transport.
- The runtime owns the correctness of connections and scopes.
Execution path
The major boundaries from authored SQL to application values.
Package boundaries
The execution core and static tooling share contracts while keeping dependency direction separate.
@sqlbraid/corecontracts + invariants@sqlbraid/templateauthoring + rendering@sqlbraid/runtimephysical lifecycledriver adaptersDB/driver bridge@sqlbraid/compilersource discovery / lowering@sqlbraid/metadatadatabase evidence@sqlbraid/codegenmodel generation@sqlbraid/toolingworkspace / semantic toolingconsumersLSP / CLI / VS Code / ViteThe four execution layers
Section titled “The four execution layers”@sqlbraid/coredefines the interfaces: logical statements, the binding SPI, the executor and provider SPI, the runtime API, the representation policy, observers, capabilities, routines and public errors.@sqlbraid/templateturns tagged templates into frozenQueryvalues. It renders explicit SQL structure intoRenderedStatementobjects that do not depend on the transport.@sqlbraid/runtimeowns leases, pinned scopes, the continuity of transactions and savepoints, the lifetime of streams, cancellation boundaries, result-kind checks and application mapping.- Driver adapters translate the logical statement and binding description into a native driver call. They normalize the native results back into SQLBraid types.
The invariant to remember
Section titled “The invariant to remember”segments.length===parameters.length + 1An ordinary ${value} interpolation is a bind value. It does not become SQL structure. Structural SQL requires an explicit helper, such as sql.ident, sql.fragment, sql.list or sql.join. sql.raw is the deliberate escape hatch.
Placeholder syntax occurs only at the binding and adapter boundary. PostgreSQL can use $1, MySQL ?, Oracle :1 and SQL Server @p1. Native-template transports can keep a different physical representation.
Resource ownership is the main job of the runtime
Section titled “Resource ownership is the main job of the runtime”A pooled materialized query does these steps:
- It acquires a lease.
- It does the physical I/O.
- It releases the lease.
- Only then does it do the asynchronous Standard Schema mapping.
A stream is different. Its cursor or result set keeps the resource until the iterator cleanup is complete.
db.session() pins one resource. It does not begin a transaction. db.tx() begins one physical transaction on a pinned resource. Nested transactions are savepoints on that same resource. They are not independent transactions.
If a use of a root or parent handle could escape to a different connection, SQLBraid rejects it. SQLBraid does not silently route it to a different connection. If transaction control or cleanup leaves a connection in an uncertain state, SQLBraid poisons or discards the resource. It does not reuse it optimistically.
Prepared, batch and bulk have different rules
Section titled “Prepared, batch and bulk have different rules”db.prepare()locks the logical SQLBraid shape. It does not promise a universal server-side prepared cache.db.batch()runs several operations on one physical use or lease. The operations can be different. A batch is not a transaction.db.bulk()applies one homogeneous command shape to many inputs. The adapter selects the physical bulk strategy.
TypePolicy is not application mapping
Section titled “TypePolicy is not application mapping”TypePolicy normalizes database and native driver values into the canonical JavaScript representation of SQLBraid. Standard Schema maps that canonical representation into application and domain values. These boundaries stay separate. Thus, the runtime does not need a universal codec framework.
Tooling is a separate plane
Section titled “Tooling is a separate plane”The runtime packages do not depend on metadata, codegen, compiler, CLI, editor or Vite packages.
@sqlbraid/compilerowns source discovery and lowering.@sqlbraid/metadatarecords database evidence.@sqlbraid/codegengenerates models from metadata and TypePolicy.@sqlbraid/toolingcombines positive evidence for LSP, CLI and editor features.
Missing metadata is unresolved evidence. It does not prove that user SQL is invalid.
Read the source in this order
Section titled “Read the source in this order”packages/core/src/:statement.ts(RenderedStatement),query.ts(Query),binding.ts(StatementBindingAdapter),executor.ts(QueryExecutor,ConnectionProvider),database.ts(Database),authoring.ts(SqlTag).index.tsonly re-exports.packages/template/src/:tag.ts(createSqlTag()) andrender.ts(the rendering path).packages/runtime/src/index.ts:createScopedDatabase()→prepareObserved()→prepare(). Thenoperations/materialized.ts:runPrepared()→leaseForUse()→physical()→finalizePhysical()→processRows().- The runtime
stream(), thensession()andtx(). - The PostgreSQL
pgStatementBinding/createPgExecutor()as a reference adapter. Then Oracle, as an adapter with many resources. - Compiler → metadata → codegen → tooling, when you work on static tooling.
For the full walkthrough and the invariants for contributors, read the English mental model in the repository. Driver implementers must also read the driver-author guide.