Skip to main content
A published table is read like any other table. Use ctx.db in a query or mutation, read through its indexes, and subscribe to it from a client. When a new publication switches in, subscribed queries rerun and receive the new rows.
bijection/orders.ts

One publication per read

A pipeline switches all of its output tables in one commit. A query or mutation reads every table at one point in time, so it reads all of a pipeline’s tables from the same publication. It never sees the new open_orders next to the old customer_totals. Published tables are not guaranteed to reflect the latest input. After an order is written, open_orders keeps serving the previous publication until the next run finishes. To depend on a particular input change, use a coverage requirement.

Unavailable tables

A published table is unavailable before its first publication, after its publication is withdrawn, and while its group is in an ownership transition. Reading it then fails with PublishedUnavailable. It is never served as an empty table. The failed read stays a dependency of the query. When the table becomes available, a subscribed query reruns without the client reconnecting. Availability is checked on every read, including cached results and paginated continuations. Withdrawing a publication, or revoking the authority it was published under, refuses its rows immediately. Rows a client already received cannot be recalled.

Paginating published tables

Paginated queries over a published table do not continue silently onto a newer publication. If the publication changes between pages, continuing from the old cursor can fail with QueryAccessChanged. Restart the read from the first page.

Knowing what is serving

To show whether a result is current, expose the pipeline’s publication method from a query. It reads the pipeline’s state and every output table at one point in time, and requires an authenticated user the access policy grants.
bijection/summaries.ts
It returns null before the pipeline is configured, and otherwise an object with these fields: An older result can keep serving while a newer one prepares or fails, so a client should check isServingSelected before reporting that a change has been published. For a single table, publications.status from bijection/server returns its publication status directly:
bijection/orders.ts
The result has serving (the serving publisher, producer, run and input evidence, or its transitioning or withdrawn state), publishedAt, preparation (the state, rows and pages of a publication being prepared) and scan (set when Bijection refuses the pipeline’s publisher declaration). status is governed by the table’s own read rule. It remains readable while the rows are unavailable, so you can diagnose why; it never returns rows.

Requiring a publication

A function can state which publication it needs, and Bijection checks it in the function’s own transaction before the handler runs. Wrap a query or mutation with publications.consuming:
bijection/orders.ts
The requirement names 1 to 8 published tables and one compatibility rule: covers is optional and holds at most 16 entries. Each names an input table and the argument that carries a checkpoint; that argument must be a required v.string(). When the requirement is not met, the function fails before its handler runs, with one of PublishedUnavailable, PublicationUnavailable, PublicationSourceUnavailable, PublicationGroupMismatch, PublicationEvidenceUnavailable, PublicationRootMismatch, PublicationRootOverlap or PublicationCoverage. A checkpoint that cannot be used fails with PublicationCheckpoint. A query does not return data and a mutation does not commit.

Checkpoints

A checkpoint names the current state of an ordinary table. Get one from a query with publications.checkpoint, for example right after your client’s mutation succeeds:
bijection/orders.ts
Pass it as the after argument of currentCustomerSummary. The query refuses with PublicationCoverage until a publication computed from that state, or a newer one, is serving. Call publications.checkpoint from a query your client calls directly, not from a nested query. It names an ordinary table; views and published tables are refused with PublicationCheckpoint.

Checking inside a handler

publications.require checks the same requirement from inside a handler, with the checkpoint given directly as after:
bijection/orders.ts
A refusal cannot be caught and ignored: even if your code catches the error, the query returns no data and the mutation does not commit. Prefer publications.consuming when the requirement applies to the whole function.

Waiting until a requirement is met

publications.readiness takes the same requirement in a query and returns { kind: "ready" } or { kind: "pending", reason } instead of failing. It is reactive: a subscribed query updates when the publication changes.
bijection/orders.ts
A ready result is not permission to act later. A mutation that depends on the publication must still check it with publications.consuming or publications.require in its own transaction.