Docs/Core concepts/Streaming queries

Core concepts · 06

Streaming queries

A streaming query is a long-lived subscription against a lattice. Instead of returning a snapshot and closing, it holds the connection open and emits a delta frame every time a matching node or edge changes.

Updated 11 June 2026 Read 9 min Stability GA Applies to v4.0 +

The delta model#

Every lattice keeps an append-only log of committed transactions. A streaming query registers a predicate against that log; the coordinator replays history up to the requested watermark, then tails the log indefinitely. Clients therefore receive two phases from a single subscription.

  • Backfill — ordered frames reconstructing current state, terminated by a sync marker.
  • Live tail — one frame per committed transaction touching the predicate.

Because both phases share a frame envelope, application code does not need a separate loading branch. Render the first frame you get and keep rendering.

Design note

Backfill and tail frames are indistinguishable except for the phase field. Treat the marker as an optional optimisation, never as a correctness requirement.

Opening a stream#

The TypeScript SDK exposes streams as async iterables. Cancellation is cooperative: breaking out of the loop tears down the socket and releases the server-side cursor within one heartbeat interval.

stream.ts
import { connect } from "@lattice/client";

const lattice = await connect({ region: "eu-west-1" });

const stream = lattice.query(`
  match (order:Order)-[:PLACED_BY]->(c:Customer)
  where order.status in ["pending","picking"]
  emit order.id, order.status, c.tier
`, { from: "watermark:latest-24h" });

for await (const frame of stream) {
  if (frame.phase === "sync") ui.markReady();
  ui.apply(frame.deltas);        // idempotent by (id, lsn)
}

Connection parameters

ParameterTypeDefaultNotes
fromwatermarknowReplay origin. Accepts LSN, timestamp, or alias.
batchinteger256Max deltas per frame during backfill.
heartbeatduration15sEmpty keepalive frame interval.
compressionenumzstdOne of none, gzip, zstd.
maxLagdurationnoneServer closes the stream if the client falls behind.

Frame envelope#

Frames are newline-delimited JSON over HTTP/2, or CBOR over the binary transport. The envelope is stable across both and versioned independently of the payload schema.

frame.json
{
  "v": 2,
  "phase": "tail",
  "lsn": "0000-4c1a-9f30",
  "emittedAt": "2026-06-11T09:14:02.418Z",
  "deltas": [
    { "op": "upsert", "id": "order_81f2",
      "fields": { "status": "picking", "tier": "gold" } }
  ]
}

Ordering guarantees

Within a single partition, frames arrive in commit order and lsn increases monotonically. Across partitions, only causal order is guaranteed — two unrelated writes may be observed in either sequence. Applications that need a global order should request consistency: "linearizable" and accept the added latency.

Backpressure#

The coordinator maintains a per-subscription buffer of 64 MiB. When a slow consumer fills it, the server applies one of three strategies, selected at open time.

  1. Block — stop reading the log until the client drains. Safest, but a single slow client can pin resources.
  2. Coalesce — collapse repeated updates to the same key into the newest value. Default for UI workloads.
  3. Drop & resync — abandon the buffer and force the client to reopen from a fresh watermark.
Careful

Coalescing is lossy for event-sourced consumers. If you need every intermediate transition, choose block and provision a dead-letter sink.

Reconnection#

Persist the last applied lsn. On reconnect, pass it as from and the coordinator resumes exactly where you stopped, provided the log segment is still retained — 7 days on standard plans, 30 on enterprise.

If the watermark has aged out, the server responds with 410 Gone and a suggested fallback watermark. Rebuild from a full backfill rather than assuming continuity.

Retry budget

Clients should use exponential backoff with full jitter, capped at 30 seconds, and abandon after 12 consecutive failures. The SDK implements this by default; override with retry: { cap, attempts }.

Limits & quotas#

LimitStandardEnterprise
Concurrent streams per key25010,000
Predicate complexity units40200
Log retention7 days30 days
Frame size1 MiB8 MiB
Sustained delta rate5k/s120k/s

Quota headers are returned on the initial handshake response and refreshed on every heartbeat frame, so long-lived clients see quota changes without reconnecting.