# Realtime

URL: /code/platform/realtime · Id: `page:code/platform/realtime`

> Realtime pushes Events, Messages and record changes to Apps and agents as they happen, resumable from a cursor.

Realtime pushes [Events](/business/nouns/event), [Messages](/business/nouns/message) and record changes to connected [Apps](/business/nouns/app) and agents as they happen. A client that drops resumes from its cursor and misses nothing.

## Stream in the SDK
Leaseline declares a `Lease` [Noun](/business/nouns/noun). Its manager screen shows each renewal the moment it lands:

```ts
import { $ } from 'startup-builder'

const cursor = localStorage.getItem('cursor') ?? undefined

for await (const event of $.stream('Lease.renewed', { cursor })) {
  console.log(event.name, event.data)
  localStorage.setItem('cursor', String(event.seq))
}
```

## Stream to a local server
The CLI forwards each Event, signed, to a local URL, and fires test Events on demand:

```bash
npx startup-builder listen Offer.subscribed --forward-to http://localhost:3000/hooks
npx startup-builder trigger Offer.subscribed
```

## Rules
| Rule | Detail |
| --- | --- |
| Selectors | A stream reads by Event selector, such as `Lease.*`, under the caller's [Permissions](/business/nouns/permission) |
| [Order](/business/nouns/order) | Every item carries a sequence number; reconnect with the last one to receive every later item in order |
| Transport | Web sockets or server-sent events at `wss://api.sb/leaseline.app/events/stream` |
| [Cost](/business/nouns/cost) | A stream is a read and creates no [Action](/business/nouns/action) per item; open connections count against a [Limit](/business/nouns/limit) per [Tenant](/business/nouns/tenant) |
| Presence | Presence and typing reach a [Channel](/business/nouns/channel)'s members live and are never stored |
| [Agents](/business/nouns/agent) | An agent in a Channel receives its Messages as they arrive; [Dashboards](/business/nouns/dashboard) refresh live |