DRAFTThis page is not published. Only visible in development mode.

Subscriptions

A subscription is a change stream over a data source. It uses the same change-data-capture flow machinery as deferred views, but instead of materializing into a storage shape, it produces an append-only log of changes that connected clients consume - the primitive behind live queries in a frontend.

Creating a subscription

The declaration mirrors a view: a column list and a pipeline. The pipeline supports from, filter, and map, so a client can subscribe to exactly the slice of state it renders:

rql
create subscription { id: int4, status: utf8 } as {
  from shop::orders
  filter { status != "draft" }
  map { id, status }
}

The change log

Each entry in the stream is a row of the declared shape plus an implicit _op column recording what happened to it: 1 for insert, 2 for update, 3 for delete. The log is append-only - an update does not rewrite an earlier entry, it appends a new one:

text
id | status    | _op
---+-----------+----
1  | placed    | 1
2  | placed    | 1
1  | shipped   | 2
2  | cancelled | 3

Subscription, view, or event?

  • --You want the current derived state, queryable at any time: a view.
  • --You want to push each change to consumers as it happens - a live-updating UI, a sync layer: a subscription.
  • --You want imperative reactions inside the database when something happens: an event with handlers.

Like deferred views, subscriptions are eventually consistent: entries are produced from the change log after the source transaction commits.

Not runnable in the browser playground
The examples on this page are static. Subscriptions are consumed over a client connection (for example WebSocket) and are not available in the in-browser WASM build that powers the runnable snippets elsewhere in these docs.