> This page location: Realtime > SDKs > TypeScript
> Full Neon documentation index: https://neon.com/docs/llms.txt

> Summary: Reference for the Realtime TypeScript SDK, covering backend query sealing, low-level client subscriptions, React integration, and TanStack DB adapter.

# TypeScript SDK

Seal queries, subscribe from clients, and sync with frameworks

The Realtime SDK is split into modules:

- [Backend](https://neon.com/docs/realtime/sdks/typescript#backend) provides a [`RealtimeServer`](https://neon.com/docs/realtime/sdks/typescript#backend-realtimeserver) that [seals queries](../guides/queries#sealing-queries)
- [Client](https://neon.com/docs/realtime/sdks/typescript#client) provides a [`RealtimeClient`](https://neon.com/docs/realtime/sdks/typescript#client-realtimeclient) that subscribes to live queries and materializes results
- [React](https://neon.com/docs/realtime/sdks/typescript#react) provides a [`RealtimeProvider`](https://neon.com/docs/realtime/sdks/typescript#react-realtimeprovider) and the [`useLiveQuery`](https://neon.com/docs/realtime/sdks/typescript#react-uselivequery) and [`useRealtimeClient`](https://neon.com/docs/realtime/sdks/typescript#react-userealtimeclient) hooks
- [TanStack DB](https://neon.com/docs/realtime/sdks/typescript#tanstack-db) provides [`realtimeCollectionOptions`](https://neon.com/docs/realtime/sdks/typescript#tanstack-db-realtimecollectionoptions) to create a [TanStack DB collection](https://tanstack.com/db/latest/docs/overview#defining-collections)
- [Drizzle](https://neon.com/docs/realtime/sdks/typescript#drizzle) and [Kysely](https://neon.com/docs/realtime/sdks/typescript#kysely) provide [live query adapters](../guides/queries#using-a-query-builder-or-orm)

**Warning: Beta: APIs may change**

The TypeScript SDK is still evolving. The APIs are subject to change.

## Backend

Import the Backend module from `@neon/realtime/server`. It runs only on your server, because it uses your Realtime secret. It defines live queries and seals them, so an untrusted client can subscribe to a query without being able to read or change it. It's taught in the [Defining queries](../guides/queries) guide.

Create the server once, then seal a query:

```ts
import { createRealtime } from "@neon/realtime/server"

const realtime = createRealtime({ secret: process.env.NEON_REALTIME_SECRET!, db: "neondb" })
const sealedQuery = await realtime.seal({ query: messagesQuery(userId, channelId) })
```

`secret` is your `NEON_REALTIME_SECRET`, written by `neon env pull --service realtime` or shown on the Realtime page in the Neon Console. `db` is the database your queries run against. [Setup](../guides/queries#setup) covers both, and [`RealtimeServerOptions`](https://neon.com/docs/realtime/sdks/typescript#backend-realtimeserveroptions) lists the other options, including [`debugMode`](../guides/subscribing#show-full-database-errors).

### Direct subscriptions

Add a `url` to `createRealtime()` and it returns a [`RealtimeDirectServer`](https://neon.com/docs/realtime/sdks/typescript#backend-realtimedirectserver), which subscribes to queries itself, for workers, trusted agents and other backend code. [Subscribe in trusted backend code](../guides/subscribing#subscribe-in-trusted-backend-code) shows how.

### Typed parameters

Most `rawSql` parameter values pass as they are. Wrap dates, JSON, `bytea` and arrays in a [`pgParam`](https://neon.com/docs/realtime/sdks/typescript#backend-pgparam) helper to name their Postgres type, as [Parameter types](../guides/queries#parameter-types) shows.

**Import specifier** `@neon/realtime/server`

### Symbols

| Symbol                                                                                                              | Kind       | Summary                                                                                                                                                                                                                                                                                                                                                     |
| ------------------------------------------------------------------------------------------------------------------- | ---------- | ----------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------- |
| [`createRealtime`](https://neon.com/docs/realtime/sdks/typescript#backend-createrealtime)                           | Function   | Create a server-only Realtime SDK. `seal()` performs local encryption and no network requests. Supplying a WebSocket `url` additionally enables trusted direct subscriptions that mint and refresh their own capabilities. Keep the project secret out of browser bundles.                                                                                  |
| [`encodeTextParameter`](https://neon.com/docs/realtime/sdks/typescript#backend-encodetextparameter)                 | Function   | Encode an already unambiguous scalar as a PostgreSQL text-format parameter. This low-level helper is intended for adapter authors. Application code using raw SQL should prefer [`pgParam`](https://neon.com/docs/realtime/sdks/typescript#backend-pgparam) for ambiguous PostgreSQL types.                                                                 |
| [`isTypedRawSqlParameter`](https://neon.com/docs/realtime/sdks/typescript#backend-istypedrawsqlparameter)           | Function   | Test whether a value was created by one of the [`pgParam`](https://neon.com/docs/realtime/sdks/typescript#backend-pgparam) helpers. This low-level helper is intended for query-adapter authors. Applications should normally pass the wrapper directly to the adapter or [`rawSql`](https://neon.com/docs/realtime/sdks/typescript#backend-rawsql).        |
| [`rawSql`](https://neon.com/docs/realtime/sdks/typescript#backend-rawsql)                                           | Function   | Define a typed raw SQL query. Values are sent separately from the SQL. Bare values use type OID `0`, asking PostgreSQL to infer their types from the SQL. Use [`pgParam`](https://neon.com/docs/realtime/sdks/typescript#backend-pgparam) when a value needs an explicit PostgreSQL encoder and built-in type OID. JavaScript `null` represents SQL `NULL`. |
| [`PostgresParameterHelpers`](https://neon.com/docs/realtime/sdks/typescript#backend-postgresparameterhelpers)       | Interface  | PostgreSQL text encoders for values that bare raw SQL cannot disambiguate.                                                                                                                                                                                                                                                                                  |
| [`PreparedLiveQuery`](https://neon.com/docs/realtime/sdks/typescript#backend-preparedlivequery)                     | Interface  | Adapter-independent query encrypted into a live-query capability.                                                                                                                                                                                                                                                                                           |
| [`PreparedLiveQueryParameter`](https://neon.com/docs/realtime/sdks/typescript#backend-preparedlivequeryparameter)   | Interface  | One PostgreSQL text-format Bind parameter in a prepared live query.                                                                                                                                                                                                                                                                                         |
| [`RawSqlQuery`](https://neon.com/docs/realtime/sdks/typescript#backend-rawsqlquery)                                 | Interface  | Parameterized raw PostgreSQL SQL carrying its declared result-row type.                                                                                                                                                                                                                                                                                     |
| [`RealtimeAdapter`](https://neon.com/docs/realtime/sdks/typescript#backend-realtimeadapter)                         | Interface  | Converts an ORM-native query into the prepared live-query representation.                                                                                                                                                                                                                                                                                   |
| [`RealtimeDirectServer`](https://neon.com/docs/realtime/sdks/typescript#backend-realtimedirectserver)               | Interface  | Server-only SDK with trusted direct-query subscriptions. Each subscription prepares and encrypts its query locally, then uses a shared low-level client and refreshes its capability automatically. It retains its rows while connecting through retryable outages and transparently replaces an expired subscription after connectivity returns.           |
| [`RealtimeDirectServerOptions`](https://neon.com/docs/realtime/sdks/typescript#backend-realtimedirectserveroptions) | Interface  | Configuration that enables trusted direct-query subscriptions.                                                                                                                                                                                                                                                                                              |
| [`RealtimeServer`](https://neon.com/docs/realtime/sdks/typescript#backend-realtimeserver)                           | Interface  | Server-only Realtime capability issuer.                                                                                                                                                                                                                                                                                                                     |
| [`RealtimeServerOptions`](https://neon.com/docs/realtime/sdks/typescript#backend-realtimeserveroptions)             | Interface  | Configuration for a server-only Realtime capability issuer.                                                                                                                                                                                                                                                                                                 |
| [`SealedLiveQuery`](https://neon.com/docs/realtime/sdks/typescript#backend-sealedlivequery)                         | Interface  | JSON-compatible sealed representation of one exact live query. The query is a short-lived bearer credential. Transport it over HTTPS and do not put it in URLs, logs, or persistent browser storage.                                                                                                                                                        |
| [`TypedRawSqlParameter`](https://neon.com/docs/realtime/sdks/typescript#backend-typedrawsqlparameter)               | Interface  | A raw SQL parameter with an explicit PostgreSQL text encoder and type hint.                                                                                                                                                                                                                                                                                 |
| [`RawSqlParameter`](https://neon.com/docs/realtime/sdks/typescript#backend-rawsqlparameter)                         | Type alias | A JavaScript value accepted as a PostgreSQL text-format parameter.                                                                                                                                                                                                                                                                                          |
| [`pgParam`](https://neon.com/docs/realtime/sdks/typescript#backend-pgparam)                                         | Variable   | Helpers for values whose PostgreSQL text encoding or type is ambiguous.                                                                                                                                                                                                                                                                                     |

### createRealtime

```ts
function createRealtime<Query = RawSqlQuery<unknown>>(options: RealtimeDirectServerOptions<Query>): RealtimeDirectServer<Query>
```

Create a server-only Realtime SDK.

`seal()` performs local encryption and no network requests. Supplying a
WebSocket `url` additionally enables trusted direct subscriptions that mint
and refresh their own capabilities. Keep the project secret out of browser
bundles.

**Returns:** A reusable capability issuer, extended with direct subscriptions
when `url` is present.

**Throws:** If the secret or database name is invalid.

#### Type parameters

| Name    | Default                | Description                                      |
| ------- | ---------------------- | ------------------------------------------------ |
| `Query` | `RawSqlQuery<unknown>` | Query object accepted by the configured adapter. |

#### Parameters

| Name      | Type                                 | Description                                                    |
| --------- | ------------------------------------ | -------------------------------------------------------------- |
| `options` | `RealtimeDirectServerOptions<Query>` | Server-only secret, database name, and optional query adapter. |

#### Returns

`RealtimeDirectServer<Query>`

```ts
function createRealtime<Query = RawSqlQuery<unknown>>(options: RealtimeServerOptions<Query>): RealtimeServer<Query>
```

Create a server-only Realtime SDK.

`seal()` performs local encryption and no network requests. Supplying a
WebSocket `url` additionally enables trusted direct subscriptions that mint
and refresh their own capabilities. Keep the project secret out of browser
bundles.

**Returns:** A reusable capability issuer, extended with direct subscriptions
when `url` is present.

**Throws:** If the secret or database name is invalid.

#### Type parameters

| Name    | Default                | Description                                      |
| ------- | ---------------------- | ------------------------------------------------ |
| `Query` | `RawSqlQuery<unknown>` | Query object accepted by the configured adapter. |

#### Parameters

| Name      | Type                           | Description                                                    |
| --------- | ------------------------------ | -------------------------------------------------------------- |
| `options` | `RealtimeServerOptions<Query>` | Server-only secret, database name, and optional query adapter. |

#### Returns

`RealtimeServer<Query>`

### encodeTextParameter

```ts
function encodeTextParameter(value: string | number | bigint | boolean | null, typeOid: number = 0): PreparedLiveQueryParameter
```

Encode an already unambiguous scalar as a PostgreSQL text-format parameter.

This low-level helper is intended for adapter authors. Application code
using raw SQL should prefer [`pgParam`](https://neon.com/docs/realtime/sdks/typescript#backend-pgparam) for ambiguous PostgreSQL types.

**Returns:** An immutable prepared parameter.

#### Parameters

| Name      | Type                                            | Description                                                 |
| --------- | ----------------------------------------------- | ----------------------------------------------------------- |
| `value`   | `string \| number \| bigint \| boolean \| null` | Scalar value, or `null` for SQL `NULL`.                     |
| `typeOid` | `number`                                        | PostgreSQL type OID hint, or `0` for SQL-context inference. |

#### Returns

`PreparedLiveQueryParameter`

### isTypedRawSqlParameter

```ts
function isTypedRawSqlParameter(value: unknown): value is TypedRawSqlParameter
```

Test whether a value was created by one of the [`pgParam`](https://neon.com/docs/realtime/sdks/typescript#backend-pgparam) helpers.

This low-level helper is intended for query-adapter authors. Applications
should normally pass the wrapper directly to the adapter or [`rawSql`](https://neon.com/docs/realtime/sdks/typescript#backend-rawsql).

#### Parameters

| Name    | Type      | Description |
| ------- | --------- | ----------- |
| `value` | `unknown` |             |

#### Returns

`value is TypedRawSqlParameter`

### rawSql

```ts
function rawSql<Row>(sql: string, parameters: readonly RawSqlParameter[] = []): RawSqlQuery<Row>
```

Define a typed raw SQL query. Values are sent separately from the SQL. Bare
values use type OID `0`, asking PostgreSQL to infer their types from the
SQL. Use [`pgParam`](https://neon.com/docs/realtime/sdks/typescript#backend-pgparam) when a value needs an explicit PostgreSQL encoder
and built-in type OID. JavaScript `null` represents SQL `NULL`.

**Returns:** An immutable query descriptor accepted by `seal()`.

#### Type parameters

| Name  | Default | Description                |
| ----- | ------- | -------------------------- |
| `Row` |         | Row returned by the query. |

#### Parameters

| Name         | Type                         | Description                                                   |
| ------------ | ---------------------------- | ------------------------------------------------------------- |
| `sql`        | `string`                     | Parameterized SQL using PostgreSQL placeholders such as `$1`. |
| `parameters` | `readonly RawSqlParameter[]` | Values in placeholder order.                                  |

#### Returns

`RawSqlQuery<Row>`

### PostgresParameterHelpers

```ts
interface PostgresParameterHelpers
```

PostgreSQL text encoders for values that bare raw SQL cannot disambiguate.

#### Members

| Name          | Type                                                                                              | Description                                                                                                                                                                                                                                                                                  |
| ------------- | ------------------------------------------------------------------------------------------------- | -------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------- |
| `array`       | `(elementType: string, values: readonly unknown[]) => TypedRawSqlParameter`                       | Encode a possibly nested PostgreSQL array. Built-in element types supply their stable array OID; database-specific or unknown element types use OID `0`. JavaScript `null` becomes a SQL NULL array element. Values are encoded immediately, so later mutations do not affect the parameter. |
| `bytea`       | `(value: Uint8Array) => TypedRawSqlParameter`                                                     | Encode bytes in PostgreSQL's hexadecimal `bytea` text format.                                                                                                                                                                                                                                |
| `date`        | `(value: string \| Date) => TypedRawSqlParameter`                                                 | Encode a JavaScript date as a PostgreSQL `date`. A `Date` uses its UTC calendar date. A string is passed through as an already encoded PostgreSQL text value.                                                                                                                                |
| `json`        | `(value: unknown) => TypedRawSqlParameter`                                                        | Encode a JavaScript value as PostgreSQL `json`.                                                                                                                                                                                                                                              |
| `jsonb`       | `(value: unknown) => TypedRawSqlParameter`                                                        | Encode a JavaScript value as PostgreSQL `jsonb`.                                                                                                                                                                                                                                             |
| `text`        | `(sqlType: string, value: string \| number \| bigint \| boolean \| null) => TypedRawSqlParameter` | Use an already encoded PostgreSQL text value for a named type. A recognized built-in type supplies its stable OID. Unknown, database-specific, and extension types use OID `0` for inference.                                                                                                |
| `timestamp`   | `(value: string \| Date) => TypedRawSqlParameter`                                                 | Encode a JavaScript date as a UTC PostgreSQL `timestamp` without time zone. A string is passed through as an already encoded PostgreSQL text value.                                                                                                                                          |
| `timestamptz` | `(value: string \| Date) => TypedRawSqlParameter`                                                 | Encode a JavaScript date as a PostgreSQL `timestamptz`. A `Date` uses its ISO 8601 representation. A string is passed through as an already encoded PostgreSQL text value.                                                                                                                   |

### PreparedLiveQuery

```ts
interface PreparedLiveQuery
```

Adapter-independent query encrypted into a live-query capability.

#### Members

| Name         | Type                                    | Description                                                             |
| ------------ | --------------------------------------- | ----------------------------------------------------------------------- |
| `parameters` | `readonly PreparedLiveQueryParameter[]` | PostgreSQL text-format Bind values and type hints in placeholder order. |
| `sql`        | `readonly string`                       | Parameterized SQL. Adapters must never interpolate runtime values here. |

### PreparedLiveQueryParameter

```ts
interface PreparedLiveQueryParameter
```

One PostgreSQL text-format Bind parameter in a prepared live query.

#### Members

| Name      | Type                      | Description                                                        |
| --------- | ------------------------- | ------------------------------------------------------------------ |
| `typeOid` | `readonly number`         | PostgreSQL type OID hint, or `0` to request SQL-context inference. |
| `value`   | `readonly string \| null` | PostgreSQL text-format value, or `null` for SQL `NULL`.            |

### RawSqlQuery

```ts
interface RawSqlQuery<Row> extends PreparedLiveQuery
```

Parameterized raw PostgreSQL SQL carrying its declared result-row type.

#### Members

| Name         | Type                                    | Description                                                             |
| ------------ | --------------------------------------- | ----------------------------------------------------------------------- |
| `parameters` | `readonly PreparedLiveQueryParameter[]` | PostgreSQL text-format Bind values and type hints in placeholder order. |
| `sql`        | `readonly string`                       | Parameterized SQL. Adapters must never interpolate runtime values here. |

### RealtimeAdapter

```ts
interface RealtimeAdapter<Query>
```

Converts an ORM-native query into the prepared live-query representation.

#### Members

| Name      | Type                                  | Description                                                                                                                                                                                      |
| --------- | ------------------------------------- | ------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------ |
| `prepare` | `(query: Query) => PreparedLiveQuery` | Convert an adapter-native query into parameterized SQL and text-format parameter values. Adapters may supply PostgreSQL type OID hints; `0` requests inference. The proxy supplies result types. |

### RealtimeDirectServer

```ts
interface RealtimeDirectServer<Query> extends RealtimeServer<Query>
```

Server-only SDK with trusted direct-query subscriptions.

Each subscription prepares and encrypts its query locally, then uses a
shared low-level client and refreshes its capability automatically. It
retains its rows while connecting through retryable outages and
transparently replaces an expired subscription after connectivity returns.

#### Members

| Name                                                                                                | Type                                                                                                                                                                                                                                                                                                                | Description                                                                                                                                                                                                                                                                                                              |
| --------------------------------------------------------------------------------------------------- | ------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------- | ------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------ |
| `close`                                                                                             | `() => void`                                                                                                                                                                                                                                                                                                        | Permanently close every direct subscription and the shared WebSocket.                                                                                                                                                                                                                                                    |
| [`seal`](https://neon.com/docs/realtime/sdks/typescript#backend-realtimedirectserverseal)           | `<ConcreteQuery>(input: SealInput<ConcreteQuery>) => Promise<SealedLiveQuery<QueryRow<ConcreteQuery>>>`                                                                                                                                                                                                             | Encrypt a concrete query as a short-lived sealed query. Raw queries produced by [`rawSql`](https://neon.com/docs/realtime/sdks/typescript#backend-rawsql) are always accepted. Other query objects are prepared by the configured adapter. SQL validation is deferred to the Realtime proxy when the capability is used. |
| [`subscribe`](https://neon.com/docs/realtime/sdks/typescript#backend-realtimedirectserversubscribe) | `<ConcreteQuery>(query: ConcreteQuery, options?: MaterializedLiveQueryOptions<QueryRow<ConcreteQuery>>) => Promise<MaterializedLiveQuerySubscription<QueryRow<ConcreteQuery>>> & <ConcreteQuery>(query: ConcreteQuery, options: RawLiveQueryOptions) => Promise<RawLiveQuerySubscription<QueryRow<ConcreteQuery>>>` | Subscribe to a query and retain its current materialized rows.                                                                                                                                                                                                                                                           |

#### RealtimeDirectServer.seal

```ts
seal<ConcreteQuery>(input: SealInput<ConcreteQuery>): Promise<SealedLiveQuery<QueryRow<ConcreteQuery>>>
```

Encrypt a concrete query as a short-lived sealed query.

Raw queries produced by [`rawSql`](https://neon.com/docs/realtime/sdks/typescript#backend-rawsql) are always accepted. Other query
objects are prepared by the configured adapter. SQL validation is deferred
to the Realtime proxy when the capability is used.

**Returns:** A JSON-compatible bearer capability with its public fingerprint
and expiry.

**Throws:** If no adapter can prepare the query or capability encryption fails.

**Parameters**

| Name    | Type                       | Description             |
| ------- | -------------------------- | ----------------------- |
| `input` | `SealInput<ConcreteQuery>` | Concrete query to seal. |

#### RealtimeDirectServer.subscribe

```ts
subscribe<ConcreteQuery>(query: ConcreteQuery, options?: MaterializedLiveQueryOptions<QueryRow<ConcreteQuery>>): Promise<MaterializedLiveQuerySubscription<QueryRow<ConcreteQuery>>>
```

Subscribe to a query and retain its current materialized rows.

**Returns:** An independently disposable subscription after its initial
capability has been minted locally.

**Throws:** If the query is invalid or the direct client has been closed.

**Parameters**

| Name       | Type                                                    | Description                                          |
| ---------- | ------------------------------------------------------- | ---------------------------------------------------- |
| `query`    | `ConcreteQuery`                                         | Concrete raw SQL or adapter-native query.            |
| `options?` | `MaterializedLiveQueryOptions<QueryRow<ConcreteQuery>>` | Materialization and optional preloaded-row settings. |

```ts
subscribe<ConcreteQuery>(query: ConcreteQuery, options: RawLiveQueryOptions): Promise<RawLiveQuerySubscription<QueryRow<ConcreteQuery>>>
```

Subscribe to complete rows and atomic change batches without retaining rows.

**Returns:** An independently disposable raw subscription after its initial
capability has been minted locally.

**Throws:** If the query is invalid or the direct client has been closed.

**Parameters**

| Name      | Type                  | Description                                         |
| --------- | --------------------- | --------------------------------------------------- |
| `query`   | `ConcreteQuery`       | Concrete raw SQL or adapter-native query.           |
| `options` | `RawLiveQueryOptions` | Set `materialize` to `false` to consume raw events. |

### RealtimeDirectServerOptions

```ts
interface RealtimeDirectServerOptions<Query> extends RealtimeServerOptions<Query>
```

Configuration that enables trusted direct-query subscriptions.

#### Members

| Name                                                                                                        | Type                                                                                                                  | Description                                                                                                                                                                                               |
| ----------------------------------------------------------------------------------------------------------- | --------------------------------------------------------------------------------------------------------------------- | --------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------- |
| `adapter?`                                                                                                  | `readonly RealtimeAdapter<Query>`                                                                                     | Adapter for ORM-native queries; omit when sealing only raw SQL.                                                                                                                                           |
| `db`                                                                                                        | `readonly string`                                                                                                     | PostgreSQL database for this SDK instance. It is embedded in every query capability. The first capability accepted on a WebSocket binds that connection to this database.                                 |
| [`debugMode?`](https://neon.com/docs/realtime/sdks/typescript#backend-realtimedirectserveroptionsdebugmode) | `readonly boolean`                                                                                                    | Include full database error details in subscription errors. Enable this only in development. Detailed errors can expose schema names, table names, column names, and other database structure to clients. |
| `logger?`                                                                                                   | `readonly RealtimeLogger`                                                                                             | Structured diagnostic sink for the internal direct-subscription client.                                                                                                                                   |
| `logLevel?`                                                                                                 | `readonly RealtimeLogLevel`                                                                                           | Minimum diagnostic level for the internal direct-subscription client.                                                                                                                                     |
| `parsers?`                                                                                                  | `readonly Readonly<Record<number, PostgreSQLBytesParser<unknown> \| PostgreSQLTextParser<unknown>> & BuiltInParsers>` | PostgreSQL result-parser overrides for trusted direct subscriptions.                                                                                                                                      |
| `secret`                                                                                                    | `readonly string`                                                                                                     | Opaque server-only credential issued by Realtime.                                                                                                                                                         |
| `url`                                                                                                       | `readonly string`                                                                                                     | Realtime WebSocket endpoint URL. Supplying it adds `subscribe()` and `close()` to the returned SDK.                                                                                                       |

#### RealtimeDirectServerOptions.debugMode

```ts
readonly debugMode?: boolean
```

Include full database error details in subscription errors.

Enable this only in development. Detailed errors can expose schema names,
table names, column names, and other database structure to clients.

**Default**

```ts
false
```

### RealtimeServer

```ts
interface RealtimeServer<Query>
```

Server-only Realtime capability issuer.

#### Members

| Name                                                                                | Type                                                                                                    | Description                                                                                                                                                                                                                                                                                                              |
| ----------------------------------------------------------------------------------- | ------------------------------------------------------------------------------------------------------- | ------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------ |
| [`seal`](https://neon.com/docs/realtime/sdks/typescript#backend-realtimeserverseal) | `<ConcreteQuery>(input: SealInput<ConcreteQuery>) => Promise<SealedLiveQuery<QueryRow<ConcreteQuery>>>` | Encrypt a concrete query as a short-lived sealed query. Raw queries produced by [`rawSql`](https://neon.com/docs/realtime/sdks/typescript#backend-rawsql) are always accepted. Other query objects are prepared by the configured adapter. SQL validation is deferred to the Realtime proxy when the capability is used. |

#### RealtimeServer.seal

```ts
seal<ConcreteQuery>(input: SealInput<ConcreteQuery>): Promise<SealedLiveQuery<QueryRow<ConcreteQuery>>>
```

Encrypt a concrete query as a short-lived sealed query.

Raw queries produced by [`rawSql`](https://neon.com/docs/realtime/sdks/typescript#backend-rawsql) are always accepted. Other query
objects are prepared by the configured adapter. SQL validation is deferred
to the Realtime proxy when the capability is used.

**Returns:** A JSON-compatible bearer capability with its public fingerprint
and expiry.

**Throws:** If no adapter can prepare the query or capability encryption fails.

**Parameters**

| Name    | Type                       | Description             |
| ------- | -------------------------- | ----------------------- |
| `input` | `SealInput<ConcreteQuery>` | Concrete query to seal. |

### RealtimeServerOptions

```ts
interface RealtimeServerOptions<Query>
```

Configuration for a server-only Realtime capability issuer.

#### Members

| Name                                                                                                  | Type                              | Description                                                                                                                                                                                               |
| ----------------------------------------------------------------------------------------------------- | --------------------------------- | --------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------- |
| `adapter?`                                                                                            | `readonly RealtimeAdapter<Query>` | Adapter for ORM-native queries; omit when sealing only raw SQL.                                                                                                                                           |
| `db`                                                                                                  | `readonly string`                 | PostgreSQL database for this SDK instance. It is embedded in every query capability. The first capability accepted on a WebSocket binds that connection to this database.                                 |
| [`debugMode?`](https://neon.com/docs/realtime/sdks/typescript#backend-realtimeserveroptionsdebugmode) | `readonly boolean`                | Include full database error details in subscription errors. Enable this only in development. Detailed errors can expose schema names, table names, column names, and other database structure to clients. |
| `secret`                                                                                              | `readonly string`                 | Opaque server-only credential issued by Realtime.                                                                                                                                                         |

#### RealtimeServerOptions.debugMode

```ts
readonly debugMode?: boolean
```

Include full database error details in subscription errors.

Enable this only in development. Detailed errors can expose schema names,
table names, column names, and other database structure to clients.

**Default**

```ts
false
```

### SealedLiveQuery

```ts
interface SealedLiveQuery<Row>
```

JSON-compatible sealed representation of one exact live query.

The query is a short-lived bearer credential. Transport it over
HTTPS and do not put it in URLs, logs, or persistent browser storage.

#### Members

| Name               | Type              | Description                                                              |
| ------------------ | ----------------- | ------------------------------------------------------------------------ |
| `capability`       | `readonly string` | Opaque encrypted bearer capability.                                      |
| `expiresAt`        | `readonly number` | Capability expiry as Unix milliseconds.                                  |
| `queryFingerprint` | `readonly string` | Stable identity used to prevent accidentally renewing a different query. |

### TypedRawSqlParameter

```ts
interface TypedRawSqlParameter extends PreparedLiveQueryParameter
```

A raw SQL parameter with an explicit PostgreSQL text encoder and type hint.

#### Members

| Name      | Type                      | Description                                                        |
| --------- | ------------------------- | ------------------------------------------------------------------ |
| `typeOid` | `readonly number`         | PostgreSQL type OID hint, or `0` to request SQL-context inference. |
| `value`   | `readonly string \| null` | PostgreSQL text-format value, or `null` for SQL `NULL`.            |

### RawSqlParameter

```ts
type RawSqlParameter = string | number | boolean | bigint | null | TypedRawSqlParameter
```

A JavaScript value accepted as a PostgreSQL text-format parameter.

### pgParam

```ts
const pgParam: PostgresParameterHelpers
```

Helpers for values whose PostgreSQL text encoding or type is ambiguous.

## Client

Import the Client module from `@neon/realtime/client`. It runs in the browser, where it subscribes to sealed queries over one shared WebSocket and keeps their results up to date. It's taught in the [Subscribing to queries](../guides/subscribing) guide.

Create one client for your app, then subscribe to a sealed query from your backend:

```ts
import { createRealtimeClient } from "@neon/realtime/client"

const client = createRealtimeClient({ url: import.meta.env.VITE_NEON_REALTIME_URL })
const subscription = client.subscribe(sealedQuery)
subscription.onChange(({ data, status }) => render(data, status))
```

Pass a `logLevel` to see what the client is doing, as [Log client diagnostics](../guides/subscribing#log-client-diagnostics) shows.

### Renewing sealed queries

Most apps pass a `refreshQuery` function to the [React or TanStack DB bindings](../guides/reactivity), which renew for them. To renew a subscription yourself, see [Renew the sealed query](../guides/subscribing#renew-the-sealed-query). Integration authors can build on [`QueryRefreshController`](https://neon.com/docs/realtime/sdks/typescript#client-queryrefreshcontroller).

**Import specifier** `@neon/realtime/client`

### Symbols

| Symbol                                                                                                                         | Kind       | Summary                                                                                                                                                                                                                                                                                                                                                                                                                    |
| ------------------------------------------------------------------------------------------------------------------------------ | ---------- | -------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------- |
| [`createRealtimeClient`](https://neon.com/docs/realtime/sdks/typescript#client-createrealtimeclient)                           | Function   | Create a reusable client that lazily opens and multiplexes a Realtime WebSocket connection that is bound by its first accepted query capability. The connection carries no user session credential; each subscription sends its own short-lived sealed query. Idle connections are heartbeat-probed, and recoverable disconnects retry with capped jittered backoff until the connection recovers or the client is closed. |
| [`defineParsers`](https://neon.com/docs/realtime/sdks/typescript#client-defineparsers)                                         | Function   | Define an OID-keyed parser preset with contextual input types. OID `pgTypeOids.bytea` receives `Uint8Array`; every other OID receives PostgreSQL text. The returned object is a frozen snapshot of the input.                                                                                                                                                                                                              |
| [`QueryRefreshController`](https://neon.com/docs/realtime/sdks/typescript#client-queryrefreshcontroller)                       | Class      | Schedules capability refreshes for framework integrations. Most applications should supply `refreshQuery` to their React or TanStack DB integration instead of constructing this class. Integration authors can use it to refresh shortly before expiry and keep retrying across capability expiry or an arbitrarily long transport outage.                                                                                |
| [`LiveQueryBatchInfo`](https://neon.com/docs/realtime/sdks/typescript#client-livequerybatchinfo)                               | Interface  | Metadata for one atomically published batch of PostgreSQL transactions.                                                                                                                                                                                                                                                                                                                                                    |
| [`LiveQueryError`](https://neon.com/docs/realtime/sdks/typescript#client-livequeryerror)                                       | Interface  | An error reported by a live-query subscription.                                                                                                                                                                                                                                                                                                                                                                            |
| [`MaterializedLiveQueryOptions`](https://neon.com/docs/realtime/sdks/typescript#client-materializedlivequeryoptions)           | Interface  | Options for the default materialized subscription.                                                                                                                                                                                                                                                                                                                                                                         |
| [`MaterializedLiveQuerySubscription`](https://neon.com/docs/realtime/sdks/typescript#client-materializedlivequerysubscription) | Interface  | A live-query subscription that also retains and publishes the current rows.                                                                                                                                                                                                                                                                                                                                                |
| [`RawLiveQueryOptions`](https://neon.com/docs/realtime/sdks/typescript#client-rawlivequeryoptions)                             | Interface  | Options for a raw, non-materializing subscription.                                                                                                                                                                                                                                                                                                                                                                         |
| [`RawLiveQueryRow`](https://neon.com/docs/realtime/sdks/typescript#client-rawlivequeryrow)                                     | Interface  | A row in a complete raw result, paired with its opaque Realtime identity.                                                                                                                                                                                                                                                                                                                                                  |
| [`RawLiveQuerySubscription`](https://neon.com/docs/realtime/sdks/typescript#client-rawlivequerysubscription)                   | Interface  | A live-query subscription that exposes ordered raw result updates.                                                                                                                                                                                                                                                                                                                                                         |
| [`RealtimeClient`](https://neon.com/docs/realtime/sdks/typescript#client-realtimeclient)                                       | Interface  | A client that multiplexes independently disposable subscriptions.                                                                                                                                                                                                                                                                                                                                                          |
| [`RealtimeClientOptions`](https://neon.com/docs/realtime/sdks/typescript#client-realtimeclientoptions)                         | Interface  | Configuration for a reusable Realtime browser client.                                                                                                                                                                                                                                                                                                                                                                      |
| [`LiveQueryChange`](https://neon.com/docs/realtime/sdks/typescript#client-livequerychange)                                     | Type alias | A row upsert or removal in an atomic publication batch.                                                                                                                                                                                                                                                                                                                                                                    |
| [`LiveQuerySnapshot`](https://neon.com/docs/realtime/sdks/typescript#client-livequerysnapshot)                                 | Type alias | Materialized query rows paired with their atomic lifecycle state.                                                                                                                                                                                                                                                                                                                                                          |
| [`LiveQueryState`](https://neon.com/docs/realtime/sdks/typescript#client-livequerystate)                                       | Type alias | Atomic lifecycle state for a live-query subscription.                                                                                                                                                                                                                                                                                                                                                                      |
| [`PostgreSQLBytesParser`](https://neon.com/docs/realtime/sdks/typescript#client-postgresqlbytesparser)                         | Type alias | A parser for PostgreSQL `bytea`, transported as decoded bytes.                                                                                                                                                                                                                                                                                                                                                             |
| [`PostgreSQLParserForOid`](https://neon.com/docs/realtime/sdks/typescript#client-postgresqlparserforoid)                       | Type alias | Parser input selected by the fixed Realtime protocol v1 OID/codec mapping.                                                                                                                                                                                                                                                                                                                                                 |
| [`PostgreSQLParsers`](https://neon.com/docs/realtime/sdks/typescript#client-postgresqlparsers)                                 | Type alias | A sparse collection of result parsers keyed by PostgreSQL type OID.                                                                                                                                                                                                                                                                                                                                                        |
| [`PostgreSQLTextParser`](https://neon.com/docs/realtime/sdks/typescript#client-postgresqltextparser)                           | Type alias | A parser for a PostgreSQL value transported with the `pg_text` codec.                                                                                                                                                                                                                                                                                                                                                      |
| [`RawLiveQueryUpdate`](https://neon.com/docs/realtime/sdks/typescript#client-rawlivequeryupdate)                               | Type alias | One authoritative raw query-result update. `rows` replaces the complete preceding result and invalidates its row-ID namespace. `changes` applies incrementally to the current result.                                                                                                                                                                                                                                      |
| [`RealtimeLogEntry`](https://neon.com/docs/realtime/sdks/typescript#client-realtimelogentry)                                   | Type alias | Structured client diagnostic passed to a configured logger. Narrowing on `event` also narrows the metadata available on the entry.                                                                                                                                                                                                                                                                                         |
| [`RealtimeLogEvent`](https://neon.com/docs/realtime/sdks/typescript#client-realtimelogevent)                                   | Type alias | Stable name for one client diagnostic event.                                                                                                                                                                                                                                                                                                                                                                               |
| [`RealtimeLogger`](https://neon.com/docs/realtime/sdks/typescript#client-realtimelogger)                                       | Type alias | Receives structured Realtime client diagnostics.                                                                                                                                                                                                                                                                                                                                                                           |
| [`RealtimeLogLevel`](https://neon.com/docs/realtime/sdks/typescript#client-realtimeloglevel)                                   | Type alias | Client-side diagnostic verbosity.                                                                                                                                                                                                                                                                                                                                                                                          |
| [`nodePostgresParsers`](https://neon.com/docs/realtime/sdks/typescript#client-nodepostgresparsers)                             | Variable   | Core result parsers matching familiar node-postgres/Neon Serverless values. Less-common and unknown OIDs are intentionally absent and fall back to their exact PostgreSQL text. Known built-in array OIDs are decoded recursively by the client using the active parser for their element OID.                                                                                                                             |
| [`pgTypeOids`](https://neon.com/docs/realtime/sdks/typescript#client-pgtypeoids)                                               | Variable   | Stable PostgreSQL type OIDs used by the built-in Realtime parsers.                                                                                                                                                                                                                                                                                                                                                         |
| [`postgresJsParsers`](https://neon.com/docs/realtime/sdks/typescript#client-postgresjsparsers)                                 | Variable   | Parsers that differ from the core defaults when matching Postgres.js. Spread this partial preset into the client's `parsers` option.                                                                                                                                                                                                                                                                                       |
| [`SealedLiveQuery`](https://neon.com/docs/realtime/sdks/typescript#client-sealedlivequery)                                     | Re-export  |                                                                                                                                                                                                                                                                                                                                                                                                                            |

### createRealtimeClient

```ts
function createRealtimeClient(options: RealtimeClientOptions): RealtimeClient
```

Create a reusable client that lazily opens and multiplexes a Realtime
WebSocket connection that is bound by its first accepted query capability.

The connection carries no user session credential; each subscription sends
its own short-lived sealed query. Idle connections are heartbeat-probed,
and recoverable disconnects retry with capped jittered backoff until the
connection recovers or the client is closed.

**Returns:** A client that opens its connection when the first query subscribes.

#### Parameters

| Name      | Type                    | Description                                                      |
| --------- | ----------------------- | ---------------------------------------------------------------- |
| `options` | `RealtimeClientOptions` | Browser client configuration, including the proxy WebSocket URL. |

#### Returns

`RealtimeClient`

### defineParsers

```ts
function defineParsers(parsers: BuiltInParsers): PostgreSQLParsers
```

Define an OID-keyed parser preset with contextual input types.

OID `pgTypeOids.bytea` receives `Uint8Array`; every other OID receives
PostgreSQL text. The returned object is a frozen snapshot of the input.

#### Parameters

| Name      | Type             | Description |
| --------- | ---------------- | ----------- |
| `parsers` | `BuiltInParsers` |             |

#### Returns

`PostgreSQLParsers`

```ts
function defineParsers(parsers: Readonly<Record<number, PostgreSQLTextParser>>): PostgreSQLParsers
```

Define an OID-keyed parser preset with contextual input types.

OID `pgTypeOids.bytea` receives `Uint8Array`; every other OID receives
PostgreSQL text. The returned object is a frozen snapshot of the input.

#### Parameters

| Name      | Type                                             | Description |
| --------- | ------------------------------------------------ | ----------- |
| `parsers` | `Readonly<Record<number, PostgreSQLTextParser>>` |             |

#### Returns

`PostgreSQLParsers`

### QueryRefreshController

```ts
class QueryRefreshController<Row>
```

Schedules capability refreshes for framework integrations.

Most applications should supply `refreshQuery` to their React or
TanStack DB integration instead of constructing this class. Integration
authors can use it to refresh shortly before expiry and keep retrying across
capability expiry or an arbitrarily long transport outage.

#### Members

| Name                                                                                                                   | Type                                                                                    | Description                                                                                                                               |
| ---------------------------------------------------------------------------------------------------------------------- | --------------------------------------------------------------------------------------- | ----------------------------------------------------------------------------------------------------------------------------------------- |
| `constructor`                                                                                                          | `new <Row>(options: QueryRefreshControllerOptions<Row>) => QueryRefreshController<Row>` |                                                                                                                                           |
| `currentQuery`                                                                                                         | `() => SealedLiveQuery<Row>`                                                            | Return the capability currently managed by this controller.                                                                               |
| [`replaceSealedQuery`](https://neon.com/docs/realtime/sdks/typescript#client-queryrefreshcontrollerreplacesealedquery) | `(query: SealedLiveQuery<Row>) => Promise<void>`                                        | Apply a replacement capability immediately and schedule its next refresh.                                                                 |
| `setRefreshCallback`                                                                                                   | `(refreshQuery: (() => Promise<SealedLiveQuery<Row>>) \| undefined) => void`            | Replace the callback used to obtain a fresh capability. Passing `undefined` disables scheduled refreshes without stopping the controller. |
| `setSubscription`                                                                                                      | `(subscription: RawLiveQuerySubscription<Row> \| undefined) => void`                    | Associate the active subscription managed by this controller.                                                                             |
| `start`                                                                                                                | `() => void`                                                                            | Start scheduling refreshes. Calling this more than once has no effect.                                                                    |
| `stop`                                                                                                                 | `() => void`                                                                            | Stop scheduling refreshes and ignore any refresh already in flight.                                                                       |

#### QueryRefreshController.replaceSealedQuery

```ts
replaceSealedQuery(query: SealedLiveQuery<Row>): Promise<void>
```

Apply a replacement capability immediately and schedule its next refresh.

**Throws:** If the replacement capability belongs to a different query, or if
applying it to the active subscription fails.

**Parameters**

| Name    | Type                   | Description |
| ------- | ---------------------- | ----------- |
| `query` | `SealedLiveQuery<Row>` |             |

### LiveQueryBatchInfo

```ts
interface LiveQueryBatchInfo
```

Metadata for one atomically published batch of PostgreSQL transactions.

#### Members

| Name    | Type                | Description                                                      |
| ------- | ------------------- | ---------------------------------------------------------------- |
| `txids` | `readonly string[]` | Exact PostgreSQL transaction IDs represented as decimal strings. |

### LiveQueryError

```ts
interface LiveQueryError extends Error
```

An error reported by a live-query subscription.

#### Members

| Name        | Type               | Description                                                            |
| ----------- | ------------------ | ---------------------------------------------------------------------- |
| `cause?`    | `unknown`          |                                                                        |
| `code`      | `readonly string`  | Stable machine-readable error code.                                    |
| `message`   | `string`           |                                                                        |
| `name`      | `string`           |                                                                        |
| `retryable` | `readonly boolean` | Whether reconnecting or obtaining a fresh sealed query may recover it. |
| `sqlState?` | `readonly string`  | PostgreSQL SQLSTATE supplied for an authenticated debug query failure. |
| `stack?`    | `string`           |                                                                        |

### MaterializedLiveQueryOptions

```ts
interface MaterializedLiveQueryOptions<Row>
```

Options for the default materialized subscription.

#### Members

| Name           | Type             | Description                                                          |
| -------------- | ---------------- | -------------------------------------------------------------------- |
| `initialData?` | `readonly Row[]` | Preloaded rows exposed while connecting to the authoritative result. |
| `materialize?` | `readonly true`  | Select materialization; omitted and `true` are equivalent.           |

### MaterializedLiveQuerySubscription

```ts
interface MaterializedLiveQuerySubscription<Row> extends RawLiveQuerySubscription<Row>
```

A live-query subscription that also retains and publishes the current rows.

#### Members

| Name                                                                                                                    | Type                                                                              | Description                                                                                                                                                                                                                                                                                     |
| ----------------------------------------------------------------------------------------------------------------------- | --------------------------------------------------------------------------------- | ----------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------- |
| [`awaitRows`](https://neon.com/docs/realtime/sdks/typescript#client-materializedlivequerysubscriptionawaitrows)         | `(matches: (rows: readonly Row[]) => boolean, timeout?: number) => Promise<void>` | Wait until the materialized rows satisfy a predicate. The current snapshot is inspected before waiting for later changes, so this also succeeds when matching rows arrived before the call.                                                                                                     |
| [`awaitTxId`](https://neon.com/docs/realtime/sdks/typescript#client-materializedlivequerysubscriptionawaittxid)         | `(txid: string, timeout?: number) => Promise<void>`                               | Wait until this subscription has applied a PostgreSQL transaction. Recently applied transaction IDs are retained so this also succeeds when the batch arrives before the caller receives the mutation response.                                                                                 |
| `getSnapshot`                                                                                                           | `() => LiveQuerySnapshot<Row>`                                                    | Return the current rows and lifecycle state atomically.                                                                                                                                                                                                                                         |
| `getState`                                                                                                              | `() => LiveQueryState`                                                            | Return the complete current lifecycle state.                                                                                                                                                                                                                                                    |
| [`onChange`](https://neon.com/docs/realtime/sdks/typescript#client-materializedlivequerysubscriptiononchange)           | `(listener: (snapshot: LiveQuerySnapshot<Row>) => void) => () => void`            | Observe row or lifecycle changes as complete snapshots. The listener runs after complete-row replacements, incremental changes, and state transitions.                                                                                                                                          |
| [`onStateChange`](https://neon.com/docs/realtime/sdks/typescript#client-materializedlivequerysubscriptiononstatechange) | `(listener: (state: LiveQueryState) => void) => () => void`                       | Observe lifecycle transitions.                                                                                                                                                                                                                                                                  |
| [`onUpdate`](https://neon.com/docs/realtime/sdks/typescript#client-materializedlivequerysubscriptiononupdate)           | `(listener: (update: RawLiveQueryUpdate<Row>) => void) => () => void`             | Observe complete-row replacements and incremental changes through one ordered update stream. Every affected materialized subscription has already applied an update before its listener runs.                                                                                                   |
| [`renew`](https://neon.com/docs/realtime/sdks/typescript#client-materializedlivequerysubscriptionrenew)                 | `(query: SealedLiveQuery<Row>) => Promise<void>`                                  | Renew this logical subscription with a capability for the same exact query. If the preceding subscription has expired, the client creates a new wire subscription while preserving this object, its listeners, and any retained rows. The replacement then produces a new authoritative result. |
| `unsubscribe`                                                                                                           | `() => void`                                                                      | Permanently close this subscription and remove its listeners.                                                                                                                                                                                                                                   |

#### MaterializedLiveQuerySubscription.awaitRows

```ts
awaitRows(matches: (rows: readonly Row[]) => boolean, timeout?: number): Promise<void>
```

Wait until the materialized rows satisfy a predicate.

The current snapshot is inspected before waiting for later changes, so
this also succeeds when matching rows arrived before the call.

**Throws:** If a supplied timeout elapses, the predicate throws, or the
subscription closes or enters a terminal error before the rows match.

**Parameters**

| Name       | Type                                | Description                                                                                                                    |
| ---------- | ----------------------------------- | ------------------------------------------------------------------------------------------------------------------------------ |
| `matches`  | `(rows: readonly Row[]) => boolean` | Predicate evaluated against each complete row snapshot.                                                                        |
| `timeout?` | `number`                            | Optional maximum wait in milliseconds. By default the promise remains pending until the rows match or the subscription closes. |

#### MaterializedLiveQuerySubscription.awaitTxId

```ts
awaitTxId(txid: string, timeout?: number): Promise<void>
```

Wait until this subscription has applied a PostgreSQL transaction.

Recently applied transaction IDs are retained so this also succeeds when
the batch arrives before the caller receives the mutation response.

**Remarks:** This does not determine whether a transaction committed, so pass only IDs
from transactions known to have committed.

**Throws:** If the timeout elapses, the transaction ID is invalid, or the
subscription fails or closes before applying the transaction.

**Parameters**

| Name       | Type     | Description                                                                                                                                                      |
| ---------- | -------- | ---------------------------------------------------------------------------------------------------------------------------------------------------------------- |
| `txid`     | `string` | PostgreSQL transaction ID as a decimal string.                                                                                                                   |
| `timeout?` | `number` | Optional maximum wait in milliseconds. By default the promise remains pending until the transaction arrives, the subscription fails, or the subscription closes. |

#### MaterializedLiveQuerySubscription.onChange

```ts
onChange(listener: (snapshot: LiveQuerySnapshot<Row>) => void): () => void
```

Observe row or lifecycle changes as complete snapshots.
The listener runs after complete-row replacements, incremental changes,
and state transitions.

**Returns:** A function that removes this listener.

**Parameters**

| Name       | Type                                         | Description |
| ---------- | -------------------------------------------- | ----------- |
| `listener` | `(snapshot: LiveQuerySnapshot<Row>) => void` |             |

#### MaterializedLiveQuerySubscription.onStateChange

```ts
onStateChange(listener: (state: LiveQueryState) => void): () => void
```

Observe lifecycle transitions.

**Returns:** A function that removes this listener.

**Parameters**

| Name       | Type                              | Description |
| ---------- | --------------------------------- | ----------- |
| `listener` | `(state: LiveQueryState) => void` |             |

#### MaterializedLiveQuerySubscription.onUpdate

```ts
onUpdate(listener: (update: RawLiveQueryUpdate<Row>) => void): () => void
```

Observe complete-row replacements and incremental changes through one
ordered update stream. Every affected materialized subscription has
already applied an update before its listener runs.

**Returns:** A function that removes this listener.

**Parameters**

| Name       | Type                                        | Description |
| ---------- | ------------------------------------------- | ----------- |
| `listener` | `(update: RawLiveQueryUpdate<Row>) => void` |             |

#### MaterializedLiveQuerySubscription.renew

```ts
renew(query: SealedLiveQuery<Row>): Promise<void>
```

Renew this logical subscription with a capability for the same exact query.
If the preceding subscription has expired, the client creates a new
wire subscription while preserving this object, its listeners, and any
retained rows. The replacement then produces a new authoritative result.

**Returns:** A promise that resolves after the proxy accepts the replacement.
Calling this while `stale` moves the subscription to `connecting`; a
subsequent authoritative result returns it to `live`.

**Throws:** If the replacement query fingerprint differs or renewal is rejected.

**Parameters**

| Name    | Type                   | Description |
| ------- | ---------------------- | ----------- |
| `query` | `SealedLiveQuery<Row>` |             |

### RawLiveQueryOptions

```ts
interface RawLiveQueryOptions
```

Options for a raw, non-materializing subscription.

#### Members

| Name          | Type             | Description                                                          |
| ------------- | ---------------- | -------------------------------------------------------------------- |
| `materialize` | `readonly false` | Disable SDK materialization and consume raw result updates directly. |

### RawLiveQueryRow

```ts
interface RawLiveQueryRow<Row>
```

A row in a complete raw result, paired with its opaque Realtime identity.

#### Members

| Name    | Type              | Description                                                     |
| ------- | ----------------- | --------------------------------------------------------------- |
| `row`   | `readonly Row`    | Decoded query row.                                              |
| `rowId` | `readonly string` | Opaque identity invalidated by the next complete `rows` update. |

### RawLiveQuerySubscription

```ts
interface RawLiveQuerySubscription<Row>
```

A live-query subscription that exposes ordered raw result updates.

#### Members

| Name                                                                                                           | Type                                                                  | Description                                                                                                                                                                                                                                                                                     |
| -------------------------------------------------------------------------------------------------------------- | --------------------------------------------------------------------- | ----------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------- |
| [`awaitTxId`](https://neon.com/docs/realtime/sdks/typescript#client-rawlivequerysubscriptionawaittxid)         | `(txid: string, timeout?: number) => Promise<void>`                   | Wait until this subscription has applied a PostgreSQL transaction. Recently applied transaction IDs are retained so this also succeeds when the batch arrives before the caller receives the mutation response.                                                                                 |
| `getState`                                                                                                     | `() => LiveQueryState`                                                | Return the complete current lifecycle state.                                                                                                                                                                                                                                                    |
| [`onStateChange`](https://neon.com/docs/realtime/sdks/typescript#client-rawlivequerysubscriptiononstatechange) | `(listener: (state: LiveQueryState) => void) => () => void`           | Observe lifecycle transitions.                                                                                                                                                                                                                                                                  |
| [`onUpdate`](https://neon.com/docs/realtime/sdks/typescript#client-rawlivequerysubscriptiononupdate)           | `(listener: (update: RawLiveQueryUpdate<Row>) => void) => () => void` | Observe complete-row replacements and incremental changes through one ordered update stream. Every affected materialized subscription has already applied an update before its listener runs.                                                                                                   |
| [`renew`](https://neon.com/docs/realtime/sdks/typescript#client-rawlivequerysubscriptionrenew)                 | `(query: SealedLiveQuery<Row>) => Promise<void>`                      | Renew this logical subscription with a capability for the same exact query. If the preceding subscription has expired, the client creates a new wire subscription while preserving this object, its listeners, and any retained rows. The replacement then produces a new authoritative result. |
| `unsubscribe`                                                                                                  | `() => void`                                                          | Permanently close this subscription and remove its listeners.                                                                                                                                                                                                                                   |

#### RawLiveQuerySubscription.awaitTxId

```ts
awaitTxId(txid: string, timeout?: number): Promise<void>
```

Wait until this subscription has applied a PostgreSQL transaction.

Recently applied transaction IDs are retained so this also succeeds when
the batch arrives before the caller receives the mutation response.

**Remarks:** This does not determine whether a transaction committed, so pass only IDs
from transactions known to have committed.

**Throws:** If the timeout elapses, the transaction ID is invalid, or the
subscription fails or closes before applying the transaction.

**Parameters**

| Name       | Type     | Description                                                                                                                                                      |
| ---------- | -------- | ---------------------------------------------------------------------------------------------------------------------------------------------------------------- |
| `txid`     | `string` | PostgreSQL transaction ID as a decimal string.                                                                                                                   |
| `timeout?` | `number` | Optional maximum wait in milliseconds. By default the promise remains pending until the transaction arrives, the subscription fails, or the subscription closes. |

#### RawLiveQuerySubscription.onStateChange

```ts
onStateChange(listener: (state: LiveQueryState) => void): () => void
```

Observe lifecycle transitions.

**Returns:** A function that removes this listener.

**Parameters**

| Name       | Type                              | Description |
| ---------- | --------------------------------- | ----------- |
| `listener` | `(state: LiveQueryState) => void` |             |

#### RawLiveQuerySubscription.onUpdate

```ts
onUpdate(listener: (update: RawLiveQueryUpdate<Row>) => void): () => void
```

Observe complete-row replacements and incremental changes through one
ordered update stream. Every affected materialized subscription has
already applied an update before its listener runs.

**Returns:** A function that removes this listener.

**Parameters**

| Name       | Type                                        | Description |
| ---------- | ------------------------------------------- | ----------- |
| `listener` | `(update: RawLiveQueryUpdate<Row>) => void` |             |

#### RawLiveQuerySubscription.renew

```ts
renew(query: SealedLiveQuery<Row>): Promise<void>
```

Renew this logical subscription with a capability for the same exact query.
If the preceding subscription has expired, the client creates a new
wire subscription while preserving this object, its listeners, and any
retained rows. The replacement then produces a new authoritative result.

**Returns:** A promise that resolves after the proxy accepts the replacement.
Calling this while `stale` moves the subscription to `connecting`; a
subsequent authoritative result returns it to `live`.

**Throws:** If the replacement query fingerprint differs or renewal is rejected.

**Parameters**

| Name    | Type                   | Description |
| ------- | ---------------------- | ----------- |
| `query` | `SealedLiveQuery<Row>` |             |

### RealtimeClient

```ts
interface RealtimeClient
```

A client that multiplexes independently disposable subscriptions.

#### Members

| Name                                                                                         | Type                                                                                                                                                                                                                            | Description                                                        |
| -------------------------------------------------------------------------------------------- | ------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------- | ------------------------------------------------------------------ |
| `close`                                                                                      | `() => void`                                                                                                                                                                                                                    | Permanently close all subscriptions and the underlying WebSocket.  |
| [`subscribe`](https://neon.com/docs/realtime/sdks/typescript#client-realtimeclientsubscribe) | `<Row>(query: SealedLiveQuery<Row>, options?: MaterializedLiveQueryOptions<Row>) => MaterializedLiveQuerySubscription<Row> & <Row>(query: SealedLiveQuery<Row>, options: RawLiveQueryOptions) => RawLiveQuerySubscription<Row>` | Start a materialized subscription, optionally with preloaded rows. |

#### RealtimeClient.subscribe

```ts
subscribe<Row>(query: SealedLiveQuery<Row>, options?: MaterializedLiveQueryOptions<Row>): MaterializedLiveQuerySubscription<Row>
```

Start a materialized subscription, optionally with preloaded rows.

**Returns:** An independently disposable materialized subscription.

**Throws:** If the query is malformed or the client is closed.

**Parameters**

| Name       | Type                                | Description                                                 |
| ---------- | ----------------------------------- | ----------------------------------------------------------- |
| `query`    | `SealedLiveQuery<Row>`              | Short-lived capability returned by the application backend. |
| `options?` | `MaterializedLiveQueryOptions<Row>` | Materialization and optional preloaded-row settings.        |

```ts
subscribe<Row>(query: SealedLiveQuery<Row>, options: RawLiveQueryOptions): RawLiveQuerySubscription<Row>
```

Start a raw subscription without retaining query rows in the SDK.

**Returns:** An independently disposable raw subscription.

**Throws:** If the query is malformed or the client is closed.

**Parameters**

| Name      | Type                   | Description                                                 |
| --------- | ---------------------- | ----------------------------------------------------------- |
| `query`   | `SealedLiveQuery<Row>` | Short-lived capability returned by the application backend. |
| `options` | `RawLiveQueryOptions`  | Set `materialize` to `false` to consume raw events.         |

### RealtimeClientOptions

```ts
interface RealtimeClientOptions
```

Configuration for a reusable Realtime browser client.

#### Members

| Name        | Type                                                                                                                  | Description                                                                                                                                                                                                                                                    |
| ----------- | --------------------------------------------------------------------------------------------------------------------- | -------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------- |
| `logger?`   | `readonly RealtimeLogger`                                                                                             | Structured diagnostic sink. It is called only for events enabled by `logLevel`; exceptions from the sink are ignored.                                                                                                                                          |
| `logLevel?` | `readonly RealtimeLogLevel`                                                                                           | Minimum client diagnostic level. The default, `silent`, emits nothing. When enabled without `logger`, entries are written to `console`.                                                                                                                        |
| `parsers?`  | `readonly Readonly<Record<number, PostgreSQLBytesParser<unknown> \| PostgreSQLTextParser<unknown>> & BuiltInParsers>` | PostgreSQL result parsers keyed by type OID. These entries override [`nodePostgresParsers`](https://neon.com/docs/realtime/sdks/typescript#client-nodepostgresparsers). The client snapshots the object when it is created, so later mutations have no effect. |
| `url`       | `readonly string`                                                                                                     | Realtime proxy WebSocket URL, using `wss:` outside local development.                                                                                                                                                                                          |

### LiveQueryChange

```ts
type LiveQueryChange<Row> = { readonly row: Row; readonly rowId: string; readonly type: "upsert" } | { readonly rowId: string; readonly type: "remove" }
```

A row upsert or removal in an atomic publication batch.

### LiveQuerySnapshot

```ts
type LiveQuerySnapshot<Row> = LiveQueryState & { data: readonly Row[] | undefined }
```

Materialized query rows paired with their atomic lifecycle state.

### LiveQueryState

```ts
type LiveQueryState = { readonly error: undefined; readonly status: "connecting" | "live" | "stale" | "closed" } | { readonly error: LiveQueryError; readonly status: "error" }
```

Atomic lifecycle state for a live-query subscription.

### PostgreSQLBytesParser

```ts
type PostgreSQLBytesParser<Value = unknown> = (value: Uint8Array) => Value
```

A parser for PostgreSQL `bytea`, transported as decoded bytes.

### PostgreSQLParserForOid

```ts
type PostgreSQLParserForOid<Oid extends number> = Oid extends typeof pgTypeOids.bytea ? PostgreSQLBytesParser : PostgreSQLTextParser
```

Parser input selected by the fixed Realtime protocol v1 OID/codec mapping.

### PostgreSQLParsers

```ts
type PostgreSQLParsers = Readonly<Record<number, PostgreSQLTextParser | PostgreSQLBytesParser> & BuiltInParsers>
```

A sparse collection of result parsers keyed by PostgreSQL type OID.

### PostgreSQLTextParser

```ts
type PostgreSQLTextParser<Value = unknown> = (value: string) => Value
```

A parser for a PostgreSQL value transported with the `pg_text` codec.

### RawLiveQueryUpdate

```ts
type RawLiveQueryUpdate<Row> = { rows: readonly RawLiveQueryRow<Row>[]; readonly type: "rows" } | { readonly batch: LiveQueryBatchInfo; changes: readonly LiveQueryChange<Row>[]; readonly type: "changes" }
```

One authoritative raw query-result update.

`rows` replaces the complete preceding result and invalidates its row-ID
namespace. `changes` applies incrementally to the current result.

### RealtimeLogEntry

```ts
type RealtimeLogEntry = { [Event in RealtimeLogEvent]: RealtimeLogEntryFor<Event> }[RealtimeLogEvent]
```

Structured client diagnostic passed to a configured logger.

Narrowing on `event` also narrows the metadata available on the entry.

### RealtimeLogEvent

```ts
type RealtimeLogEvent = keyof RealtimeLogEventDefinition
```

Stable name for one client diagnostic event.

### RealtimeLogger

```ts
type RealtimeLogger = (entry: RealtimeLogEntry) => void
```

Receives structured Realtime client diagnostics.

### RealtimeLogLevel

```ts
type RealtimeLogLevel = "silent" | "error" | "warn" | "info" | "debug"
```

Client-side diagnostic verbosity.

### nodePostgresParsers

```ts
const nodePostgresParsers: PostgreSQLParsers
```

Core result parsers matching familiar node-postgres/Neon Serverless values.

Less-common and unknown OIDs are intentionally absent and fall back to their
exact PostgreSQL text. Known built-in array OIDs are decoded recursively by
the client using the active parser for their element OID.

### pgTypeOids

```ts
const pgTypeOids: Readonly<{ readonly bit: 1560; readonly bitArray: 1561; readonly bool: 16; readonly boolArray: 1000; readonly box: 603; readonly boxArray: 1020; readonly bpchar: 1042; readonly bpcharArray: 1014; readonly bytea: 17; readonly byteaArray: 1001; readonly char: 18; readonly charArray: 1002; readonly cidr: 650; readonly cidrArray: 651; readonly circle: 718; readonly circleArray: 719; readonly cstring: 2275; readonly cstringArray: 1263; readonly date: 1082; readonly dateArray: 1182; readonly float4: 700; readonly float4Array: 1021; readonly float8: 701; readonly float8Array: 1022; readonly inet: 869; readonly inetArray: 1041; readonly int2: 21; readonly int2Array: 1005; readonly int4: 23; readonly int4Array: 1007; readonly int8: 20; readonly int8Array: 1016; readonly interval: 1186; readonly intervalArray: 1187; readonly json: 114; readonly jsonArray: 199; readonly jsonb: 3802; readonly jsonbArray: 3807; readonly line: 628; readonly lineArray: 629; readonly lseg: 601; readonly lsegArray: 1018; readonly macaddr: 829; readonly macaddr8: 774; readonly macaddr8Array: 775; readonly macaddrArray: 1040; readonly money: 790; readonly moneyArray: 791; readonly name: 19; readonly nameArray: 1003; readonly numeric: 1700; readonly numericArray: 1231; readonly oid: 26; readonly oidArray: 1028; readonly path: 602; readonly pathArray: 1019; readonly pgLsn: 3220; readonly pgLsnArray: 3221; readonly point: 600; readonly pointArray: 1017; readonly polygon: 604; readonly polygonArray: 1027; readonly text: 25; readonly textArray: 1009; readonly time: 1083; readonly timeArray: 1183; readonly timestamp: 1114; readonly timestampArray: 1115; readonly timestamptz: 1184; readonly timestamptzArray: 1185; readonly timetz: 1266; readonly timetzArray: 1270; readonly uuid: 2950; readonly uuidArray: 2951; readonly varbit: 1562; readonly varbitArray: 1563; readonly varchar: 1043; readonly varcharArray: 1015; readonly xml: 142; readonly xmlArray: 143 }>
```

Stable PostgreSQL type OIDs used by the built-in Realtime parsers.

### postgresJsParsers

```ts
const postgresJsParsers: PostgreSQLParsers
```

Parsers that differ from the core defaults when matching Postgres.js.
Spread this partial preset into the client's `parsers` option.

### SealedLiveQuery

Re-exported from [Backend](https://neon.com/docs/realtime/sdks/typescript#backend-sealedlivequery).

## React

Import the React bindings from `@neon/realtime-react`. They run in your React frontend: [`RealtimeProvider`](https://neon.com/docs/realtime/sdks/typescript#react-realtimeprovider) shares one client, [`useLiveQuery`](https://neon.com/docs/realtime/sdks/typescript#react-uselivequery) subscribes a component to a sealed query, and [`useRealtimeClient`](https://neon.com/docs/realtime/sdks/typescript#react-userealtimeclient) returns the shared client. They're taught in the [React section](../guides/reactivity#react) of the reactivity guide.

**Import specifier** `@neon/realtime-react`

### Symbols

| Symbol                                                                                                | Kind       | Summary                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                    |
| ----------------------------------------------------------------------------------------------------- | ---------- | ---------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------- |
| [`RealtimeProvider`](https://neon.com/docs/realtime/sdks/typescript#react-realtimeprovider)           | Function   | Provide one shared Realtime client to descendant [`useLiveQuery`](https://neon.com/docs/realtime/sdks/typescript#react-uselivequery) and [`useRealtimeClient`](https://neon.com/docs/realtime/sdks/typescript#react-userealtimeclient) hooks. Create the client once for the browser application. The provider does not fetch sealed queries or close the client when it unmounts.                                                                                                                                                                         |
| [`useLiveQuery`](https://neon.com/docs/realtime/sdks/typescript#react-uselivequery)                   | Function   | Subscribe to a sealed query and expose its materialized snapshot to React. The hook owns subscription cleanup.                                                                                                                                                                                                                                                                                                                                                                                                                                             |
| [`useRealtimeClient`](https://neon.com/docs/realtime/sdks/typescript#react-userealtimeclient)         | Function   | Read the shared Realtime client from the nearest [`RealtimeProvider`](https://neon.com/docs/realtime/sdks/typescript#react-realtimeprovider). Use it alongside [`useLiveQuery`](https://neon.com/docs/realtime/sdks/typescript#react-uselivequery) when a component needs the client itself: to pass it to `realtimeCollectionOptions()` from `@neon/realtime-tanstack`, or to call `subscribe()` with a sealed query directly. Subscriptions opened through `subscribe()` are not owned by React, so call `unsubscribe()` when they are no longer needed. |
| [`RealtimeProviderProps`](https://neon.com/docs/realtime/sdks/typescript#react-realtimeproviderprops) | Interface  | Props accepted by [`RealtimeProvider`](https://neon.com/docs/realtime/sdks/typescript#react-realtimeprovider).                                                                                                                                                                                                                                                                                                                                                                                                                                             |
| [`UseLiveQueryOptions`](https://neon.com/docs/realtime/sdks/typescript#react-uselivequeryoptions)     | Interface  | Options for [`useLiveQuery`](https://neon.com/docs/realtime/sdks/typescript#react-uselivequery).                                                                                                                                                                                                                                                                                                                                                                                                                                                           |
| [`UseLiveQueryResult`](https://neon.com/docs/realtime/sdks/typescript#react-uselivequeryresult)       | Type alias | React-facing snapshot and lower-level utilities returned by `useLiveQuery()`.                                                                                                                                                                                                                                                                                                                                                                                                                                                                              |
| [`UseLiveQueryUtils`](https://neon.com/docs/realtime/sdks/typescript#react-uselivequeryutils)         | Type alias | Stable imperative access to the hook's underlying materialized subscription. Cleanup remains owned by React, so `unsubscribe()` is intentionally omitted.                                                                                                                                                                                                                                                                                                                                                                                                  |

### RealtimeProvider

```ts
function RealtimeProvider(props: RealtimeProviderProps): ReactElement
```

Provide one shared Realtime client to descendant [`useLiveQuery`](https://neon.com/docs/realtime/sdks/typescript#react-uselivequery) and
[`useRealtimeClient`](https://neon.com/docs/realtime/sdks/typescript#react-userealtimeclient) hooks.

Create the client once for the browser application. The provider does not
fetch sealed queries or close the client when it unmounts.

**Returns:** A context provider for Realtime hooks.

#### Parameters

| Name    | Type                    | Description                              |
| ------- | ----------------------- | ---------------------------------------- |
| `props` | `RealtimeProviderProps` | Shared client and descendant React tree. |

#### Returns

`ReactElement`

### useLiveQuery

```ts
function useLiveQuery<Row>(query: SealedLiveQuery<Row>, options: UseLiveQueryOptions<Row> = {}): UseLiveQueryResult<Row>
```

Subscribe to a sealed query and expose its materialized snapshot to
React. The hook owns subscription cleanup.

**Returns:** The current rows and lifecycle state plus stable subscription
utilities.

**Throws:** If used outside a [`RealtimeProvider`](https://neon.com/docs/realtime/sdks/typescript#react-realtimeprovider).

#### Type parameters

| Name  | Default | Description                  |
| ----- | ------- | ---------------------------- |
| `Row` |         | Row inferred from the query. |

#### Parameters

| Name      | Type                       | Description                                              |
| --------- | -------------------------- | -------------------------------------------------------- |
| `query`   | `SealedLiveQuery<Row>`     | Capability obtained from the application backend.        |
| `options` | `UseLiveQueryOptions<Row>` | Optional preloaded rows and capability-refresh callback. |

#### Returns

`UseLiveQueryResult<Row>`

### useRealtimeClient

```ts
function useRealtimeClient(): RealtimeClient
```

Read the shared Realtime client from the nearest [`RealtimeProvider`](https://neon.com/docs/realtime/sdks/typescript#react-realtimeprovider).

Use it alongside [`useLiveQuery`](https://neon.com/docs/realtime/sdks/typescript#react-uselivequery) when a component needs the client
itself: to pass it to `realtimeCollectionOptions()` from
`@neon/realtime-tanstack`, or to call `subscribe()` with a sealed query
directly. Subscriptions opened through `subscribe()` are not owned by React,
so call `unsubscribe()` when they are no longer needed.

**Returns:** The client passed to the nearest provider.

**Throws:** If used outside a [`RealtimeProvider`](https://neon.com/docs/realtime/sdks/typescript#react-realtimeprovider).

**Example**

```tsx
import type { SealedLiveQuery } from "@neon/realtime/client";
import { useRealtimeClient } from "@neon/realtime-react";
import { realtimeCollectionOptions } from "@neon/realtime-tanstack";
import { createCollection } from "@tanstack/db";
import { useMemo } from "react";

interface Todo {
  id: string;
  title: string;
}

function useTodos(query: SealedLiveQuery<Todo>) {
  const client = useRealtimeClient();
  return useMemo(
    () =>
      createCollection(realtimeCollectionOptions({
        client,
        query,
        getKey: (todo) => todo.id,
      })),
    [client, query],
  );
}
```

#### Returns

`RealtimeClient`

### RealtimeProviderProps

```ts
interface RealtimeProviderProps
```

Props accepted by [`RealtimeProvider`](https://neon.com/docs/realtime/sdks/typescript#react-realtimeprovider).

#### Members

| Name       | Type                      | Description                                                                                                                                                                                                       |
| ---------- | ------------------------- | ----------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------- |
| `children` | `readonly ReactNode`      | React subtree that may call [`useLiveQuery`](https://neon.com/docs/realtime/sdks/typescript#react-uselivequery) or [`useRealtimeClient`](https://neon.com/docs/realtime/sdks/typescript#react-userealtimeclient). |
| `client`   | `readonly RealtimeClient` | Shared browser client made available to descendant hooks.                                                                                                                                                         |

### UseLiveQueryOptions

```ts
interface UseLiveQueryOptions<Row>
```

Options for [`useLiveQuery`](https://neon.com/docs/realtime/sdks/typescript#react-uselivequery).

#### Members

| Name            | Type                                           | Description                                                                                                                                        |
| --------------- | ---------------------------------------------- | -------------------------------------------------------------------------------------------------------------------------------------------------- |
| `initialData?`  | `readonly Row[]`                               | Server-rendered or otherwise preloaded rows exposed while connecting.                                                                              |
| `refreshQuery?` | `readonly () => Promise<SealedLiveQuery<Row>>` | Obtain a replacement capability for the same exact query before expiry. Transient failures are retried while the current capability remains valid. |

### UseLiveQueryResult

```ts
type UseLiveQueryResult<Row> = LiveQuerySnapshot<Row> & { readonly utils: UseLiveQueryUtils<Row> }
```

React-facing snapshot and lower-level utilities returned by `useLiveQuery()`.

### UseLiveQueryUtils

```ts
type UseLiveQueryUtils<Row> = Omit<MaterializedLiveQuerySubscription<Row>, "unsubscribe">
```

Stable imperative access to the hook's underlying materialized subscription.

Cleanup remains owned by React, so `unsubscribe()` is intentionally omitted.

## TanStack DB

Import the TanStack DB adapter from `@neon/realtime-tanstack`. It runs in the browser, where [`realtimeCollectionOptions`](https://neon.com/docs/realtime/sdks/typescript#tanstack-db-realtimecollectionoptions) turns a sealed query into a TanStack DB collection. It's taught in the [TanStack DB section](../guides/reactivity#tanstack-db) of the reactivity guide. The mutations guide covers [optimistic writes](../guides/mutations#with-tanstack-db-collections), and the SSR guide covers [hydration](../guides/ssr#with-tanstack-db).

**Import specifier** `@neon/realtime-tanstack`

### Symbols

| Symbol                                                                                                                | Kind       | Summary                                                                                                                                                         |
| --------------------------------------------------------------------------------------------------------------------- | ---------- | --------------------------------------------------------------------------------------------------------------------------------------------------------------- |
| [`realtimeCollectionOptions`](https://neon.com/docs/realtime/sdks/typescript#tanstack-db-realtimecollectionoptions)   | Function   | Create TanStack DB collection options backed by a raw live-query subscription. Complete-row replacements and committed change batches are applied atomically.   |
| [`RealtimeCollectionConfig`](https://neon.com/docs/realtime/sdks/typescript#tanstack-db-realtimecollectionconfig)     | Interface  | Configuration for a Realtime-backed TanStack DB collection. The adapter owns `sync`, uses eager synchronization, and supplies its own collection utilities.     |
| [`RealtimeCollectionUtils`](https://neon.com/docs/realtime/sdks/typescript#tanstack-db-realtimecollectionutils)       | Interface  | Utilities attached to a Realtime-backed TanStack DB collection.                                                                                                 |
| [`RealtimeCollectionOptions`](https://neon.com/docs/realtime/sdks/typescript#tanstack-db-realtimecollectionoptions-2) | Type alias | TanStack DB collection options produced by [`realtimeCollectionOptions`](https://neon.com/docs/realtime/sdks/typescript#tanstack-db-realtimecollectionoptions). |

### realtimeCollectionOptions

```ts
function realtimeCollectionOptions<Row extends object, Key extends string | number = string | number, Schema extends StandardSchemaV1<unknown, unknown> = never>(config: RealtimeCollectionConfig<Row, Key, Schema>): RealtimeCollectionOptions<Row, Key, Schema>
```

Create TanStack DB collection options backed by a raw live-query subscription.
Complete-row replacements and committed change batches are applied atomically.

**Returns:** Collection options to pass to TanStack DB's `createCollection()`.

#### Type parameters

| Name     | Default            | Description                                   |
| -------- | ------------------ | --------------------------------------------- |
| `Row`    |                    | Object row synchronized into the collection.  |
| `Key`    | `string \| number` | Stable key returned by `getKey`.              |
| `Schema` | `never`            | Optional Standard Schema used by TanStack DB. |

#### Parameters

| Name     | Type                                         | Description                                                                   |
| -------- | -------------------------------------------- | ----------------------------------------------------------------------------- |
| `config` | `RealtimeCollectionConfig<Row, Key, Schema>` | Live-query subscription settings and ordinary TanStack DB collection options. |

#### Returns

`RealtimeCollectionOptions<Row, Key, Schema>`

### RealtimeCollectionConfig

```ts
interface RealtimeCollectionConfig<Row extends object, Key extends string | number = string | number, Schema extends StandardSchemaV1 = never> extends Omit<BaseCollectionConfig<Row, Key, Schema, RealtimeCollectionUtils, void>, "syncMode" | "utils">
```

Configuration for a Realtime-backed TanStack DB collection.

The adapter owns `sync`, uses eager synchronization, and supplies its own
collection utilities.

#### Members

| Name                                                                                                                       | Type                                                        | Description                                                                                                                                                                                                                                                                                                                                                                                                            |
| -------------------------------------------------------------------------------------------------------------------------- | ----------------------------------------------------------- | ---------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------- |
| [`autoIndex?`](https://neon.com/docs/realtime/sdks/typescript#tanstack-db-realtimecollectionconfigautoindex)               | `"off" \| "eager"`                                          | Auto-indexing mode for the collection. When enabled, indexes will be automatically created for simple where expressions.                                                                                                                                                                                                                                                                                               |
| `client`                                                                                                                   | `readonly RealtimeClient`                                   | Reusable low-level Realtime client.                                                                                                                                                                                                                                                                                                                                                                                    |
| [`compare?`](https://neon.com/docs/realtime/sdks/typescript#tanstack-db-realtimecollectionconfigcompare)                   | `(x: Row, y: Row) => number`                                | Optional function to compare two items. This is used to order the items in the collection.                                                                                                                                                                                                                                                                                                                             |
| [`defaultIndexType?`](https://neon.com/docs/realtime/sdks/typescript#tanstack-db-realtimecollectionconfigdefaultindextype) | `IndexConstructor<Key>`                                     | Default index type to use when creating indexes without an explicit type. Required for auto-indexing. Import from '@tanstack/db'.                                                                                                                                                                                                                                                                                      |
| `defaultStringCollation?`                                                                                                  | `StringCollationConfig`                                     | Specifies how to compare data in the collection. This should be configured to match data ordering on the backend. E.g., when using the Electric DB collection these options should match the database's collation settings.                                                                                                                                                                                            |
| `gcTime?`                                                                                                                  | `number`                                                    | Time in milliseconds after which the collection will be garbage collected when it has no active subscribers. Defaults to 5 minutes (300000ms).                                                                                                                                                                                                                                                                         |
| `getKey`                                                                                                                   | `readonly (row: Row) => Key`                                | Derive the stable unique TanStack DB key for a row.                                                                                                                                                                                                                                                                                                                                                                    |
| `id?`                                                                                                                      | `string`                                                    |                                                                                                                                                                                                                                                                                                                                                                                                                        |
| [`onDelete?`](https://neon.com/docs/realtime/sdks/typescript#tanstack-db-realtimecollectionconfigondelete)                 | `DeleteMutationFn<Row, Key, RealtimeCollectionUtils, void>` | Optional asynchronous handler function called before a delete operation                                                                                                                                                                                                                                                                                                                                                |
| [`onInsert?`](https://neon.com/docs/realtime/sdks/typescript#tanstack-db-realtimecollectionconfigoninsert)                 | `InsertMutationFn<Row, Key, RealtimeCollectionUtils, void>` | Optional asynchronous handler function called before an insert operation                                                                                                                                                                                                                                                                                                                                               |
| [`onUpdate?`](https://neon.com/docs/realtime/sdks/typescript#tanstack-db-realtimecollectionconfigonupdate)                 | `UpdateMutationFn<Row, Key, RealtimeCollectionUtils, void>` | Optional asynchronous handler function called before an update operation                                                                                                                                                                                                                                                                                                                                               |
| `query`                                                                                                                    | `readonly SealedLiveQuery<Row>`                             | Initial query for the exact query backing this collection.                                                                                                                                                                                                                                                                                                                                                             |
| `refreshQuery?`                                                                                                            | `readonly () => Promise<SealedLiveQuery<Row>>`              | Obtain a replacement capability for the same exact query before expiry. Transient failures are retried while the current capability remains valid.                                                                                                                                                                                                                                                                     |
| `schema?`                                                                                                                  | `Schema`                                                    |                                                                                                                                                                                                                                                                                                                                                                                                                        |
| [`startSync?`](https://neon.com/docs/realtime/sdks/typescript#tanstack-db-realtimecollectionconfigstartsync)               | `boolean`                                                   | Whether to eagerly start syncing on collection creation. When true, syncing begins immediately. When false, syncing starts when the first subscriber attaches. Note: Even with startSync=true, collections will pause syncing when there are no active subscribers (typically when components querying the collection unmount), resuming when new subscribers attach. This preserves normal staleTime/gcTime behavior. |

#### RealtimeCollectionConfig.autoIndex

```ts
autoIndex?: "off" | "eager"
```

Auto-indexing mode for the collection.
When enabled, indexes will be automatically created for simple where expressions.

**Default**

```ts
"off"
```

- "off": No automatic indexing (default). Use explicit indexes for better bundle size.
- "eager": Automatically create indexes for simple where expressions in subscribeChanges.
  Requires setting defaultIndexType.

#### RealtimeCollectionConfig.compare

```ts
compare?: (x: Row, y: Row) => number
```

Optional function to compare two items.
This is used to order the items in the collection.

**Example**

```ts
// For a collection with a 'createdAt' field
compare: (x, y) => x.createdAt.getTime() - y.createdAt.getTime()
```

#### RealtimeCollectionConfig.defaultIndexType

```ts
defaultIndexType?: IndexConstructor<Key>
```

Default index type to use when creating indexes without an explicit type.
Required for auto-indexing. Import from '@tanstack/db'.

**Example**

```ts
import { BasicIndex } from '@tanstack/db'
const collection = createCollection({
  defaultIndexType: BasicIndex,
  autoIndex: 'eager',
  // ...
})
```

#### RealtimeCollectionConfig.onDelete

```ts
onDelete?: DeleteMutationFn<Row, Key, RealtimeCollectionUtils, void>
```

Optional asynchronous handler function called before a delete operation

**Parameter `params`:** Object containing transaction and collection information

**Returns:** Promise resolving to any value

**Example**

```ts
// Basic delete handler
onDelete: async ({ transaction, collection }) => {
  const deletedKey = transaction.mutations[0].key
  await api.deleteTodo(deletedKey)
}
```

**Example**

```ts
// Delete handler with multiple items
onDelete: async ({ transaction, collection }) => {
  const keysToDelete = transaction.mutations.map(m => m.key)
  await api.deleteTodos(keysToDelete)
}
```

**Example**

```ts
// Delete handler with confirmation
onDelete: async ({ transaction, collection }) => {
  const mutation = transaction.mutations[0]
  const shouldDelete = await confirmDeletion(mutation.original)
  if (!shouldDelete) {
    throw new Error('Delete cancelled by user')
  }
  await api.deleteTodo(mutation.original.id)
}
```

**Example**

```ts
// Delete handler with optimistic rollback
onDelete: async ({ transaction, collection }) => {
  const mutation = transaction.mutations[0]
  try {
    await api.deleteTodo(mutation.original.id)
  } catch (error) {
    // Transaction will automatically rollback optimistic changes
    console.error('Delete failed, rolling back:', error)
    throw error
  }
}
```

#### RealtimeCollectionConfig.onInsert

```ts
onInsert?: InsertMutationFn<Row, Key, RealtimeCollectionUtils, void>
```

Optional asynchronous handler function called before an insert operation

**Parameter `params`:** Object containing transaction and collection information

**Returns:** Promise resolving to any value

**Example**

```ts
// Basic insert handler
onInsert: async ({ transaction, collection }) => {
  const newItem = transaction.mutations[0].modified
  await api.createTodo(newItem)
}
```

**Example**

```ts
// Insert handler with multiple items
onInsert: async ({ transaction, collection }) => {
  const items = transaction.mutations.map(m => m.modified)
  await api.createTodos(items)
}
```

**Example**

```ts
// Insert handler with error handling
onInsert: async ({ transaction, collection }) => {
  try {
    const newItem = transaction.mutations[0].modified
    const result = await api.createTodo(newItem)
    return result
  } catch (error) {
    console.error('Insert failed:', error)
    throw error // This will cause the transaction to fail
  }
}
```

**Example**

```ts
// Insert handler with metadata
onInsert: async ({ transaction, collection }) => {
  const mutation = transaction.mutations[0]
  await api.createTodo(mutation.modified, {
    source: mutation.metadata?.source,
    timestamp: mutation.createdAt
  })
}
```

#### RealtimeCollectionConfig.onUpdate

```ts
onUpdate?: UpdateMutationFn<Row, Key, RealtimeCollectionUtils, void>
```

Optional asynchronous handler function called before an update operation

**Parameter `params`:** Object containing transaction and collection information

**Returns:** Promise resolving to any value

**Example**

```ts
// Basic update handler
onUpdate: async ({ transaction, collection }) => {
  const updatedItem = transaction.mutations[0].modified
  await api.updateTodo(updatedItem.id, updatedItem)
}
```

**Example**

```ts
// Update handler with partial updates
onUpdate: async ({ transaction, collection }) => {
  const mutation = transaction.mutations[0]
  const changes = mutation.changes // Only the changed fields
  await api.updateTodo(mutation.original.id, changes)
}
```

**Example**

```ts
// Update handler with multiple items
onUpdate: async ({ transaction, collection }) => {
  const updates = transaction.mutations.map(m => ({
    id: m.key,
    changes: m.changes
  }))
  await api.updateTodos(updates)
}
```

**Example**

```ts
// Update handler with optimistic rollback
onUpdate: async ({ transaction, collection }) => {
  const mutation = transaction.mutations[0]
  try {
    await api.updateTodo(mutation.original.id, mutation.changes)
  } catch (error) {
    // Transaction will automatically rollback optimistic changes
    console.error('Update failed, rolling back:', error)
    throw error
  }
}
```

#### RealtimeCollectionConfig.startSync

```ts
startSync?: boolean
```

Whether to eagerly start syncing on collection creation.
When true, syncing begins immediately. When false, syncing starts when the first subscriber attaches.

Note: Even with startSync=true, collections will pause syncing when there are no active
subscribers (typically when components querying the collection unmount), resuming when new
subscribers attach. This preserves normal staleTime/gcTime behavior.

**Default**

```ts
false
```

### RealtimeCollectionUtils

```ts
interface RealtimeCollectionUtils extends UtilsRecord
```

Utilities attached to a Realtime-backed TanStack DB collection.

#### Members

| Name                                                                                                       | Type                                                   | Description                                                                                                                                                   |
| ---------------------------------------------------------------------------------------------------------- | ------------------------------------------------------ | ------------------------------------------------------------------------------------------------------------------------------------------------------------- |
| [`awaitTxId`](https://neon.com/docs/realtime/sdks/typescript#tanstack-db-realtimecollectionutilsawaittxid) | `(txid: string, timeout?: number) => Promise<boolean>` | Wait until this query has processed a known committed PostgreSQL transaction. Covered row changes enter TanStack DB's causal sync queue before this resolves. |
| `[key: string]`                                                                                            | `any`                                                  |                                                                                                                                                               |

#### RealtimeCollectionUtils.awaitTxId

```ts
awaitTxId(txid: string, timeout?: number): Promise<boolean>
```

Wait until this query has processed a known committed PostgreSQL transaction.
Covered row changes enter TanStack DB's causal sync queue before this resolves.

**Remarks:** This does not determine whether a transaction committed, so pass only IDs
from transactions known to have committed.

**Throws:** If a supplied timeout elapses or the collection is cleaned up.

**Parameters**

| Name       | Type     | Description                                                                                                                                   |
| ---------- | -------- | --------------------------------------------------------------------------------------------------------------------------------------------- |
| `txid`     | `string` | PostgreSQL transaction ID as a decimal string.                                                                                                |
| `timeout?` | `number` | Optional maximum wait in milliseconds. By default, the promise remains pending until the transaction arrives or the collection is cleaned up. |

### RealtimeCollectionOptions

```ts
type RealtimeCollectionOptions<Row extends object, Key extends string | number, Schema extends StandardSchemaV1> = Omit<CollectionConfig<Row, Key, Schema, RealtimeCollectionUtils>, "utils"> & { readonly utils: RealtimeCollectionUtils }
```

TanStack DB collection options produced by [`realtimeCollectionOptions`](https://neon.com/docs/realtime/sdks/typescript#tanstack-db-realtimecollectionoptions).

## Drizzle

Import the Drizzle adapter from `@neon/realtime-drizzle`. It runs on your server: pass `drizzleAdapter()` as the `adapter` option to `createRealtime()`, then seal Drizzle selects like any other query. It's taught in [Using a query builder or ORM](../guides/queries#using-a-query-builder-or-orm), and the [Drizzle example](../examples/drizzle) goes further.

**Import specifier** `@neon/realtime-drizzle`

### Symbols

| Symbol                                                                                    | Kind     | Summary                                                                                                                                                                                                                                                                            |
| ----------------------------------------------------------------------------------------- | -------- | ---------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------- |
| [`drizzleAdapter`](https://neon.com/docs/realtime/sdks/typescript#drizzle-drizzleadapter) | Function | Prepare concrete Drizzle PostgreSQL selects as live queries. Drizzle supplies parameterized SQL and driver-ready values. Every parameter uses OID `0`, allowing PostgreSQL to infer its type from SQL context. The proxy returns result metadata when it accepts the subscription. |

### drizzleAdapter

```ts
function drizzleAdapter(): RealtimeAdapter<ConcretePgSelectQuery>
```

Prepare concrete Drizzle PostgreSQL selects as live queries.

Drizzle supplies parameterized SQL and driver-ready values. Every parameter
uses OID `0`, allowing PostgreSQL to infer its type from SQL context. The
proxy returns result metadata when it accepts the subscription.

**Returns:** An adapter to pass to `createRealtime()` on the application backend.

#### Returns

`RealtimeAdapter<ConcretePgSelectQuery>`

### Drizzle client

Import `drizzleParsers` from `@neon/realtime-drizzle/client`. It runs in the browser: spread it into the client's `parsers` option so dates and timestamps decode the way Drizzle decodes them. The [Drizzle example](../examples/drizzle) shows it in use.

**Import specifier** `@neon/realtime-drizzle/client`

### Symbols

| Symbol                                                                                           | Kind     | Summary                                                                                                                                                                                                                                                                                                                                             |
| ------------------------------------------------------------------------------------------------ | -------- | --------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------- |
| [`drizzleParsers`](https://neon.com/docs/realtime/sdks/typescript#drizzle-client-drizzleparsers) | Variable | Parser overrides for Drizzle-compatible hydrated values. PostgreSQL `date` remains a string and zone-less `timestamp` is interpreted as UTC, matching Drizzle's default PostgreSQL column modes. Spread this preset into `createRealtimeClient({ parsers })`. Per-column Drizzle modes are intentionally outside this OID-only compatibility layer. |

### drizzleParsers

```ts
const drizzleParsers: PostgreSQLParsers
```

Parser overrides for Drizzle-compatible hydrated values.

PostgreSQL `date` remains a string and zone-less `timestamp` is interpreted
as UTC, matching Drizzle's default PostgreSQL column modes. Spread this
preset into `createRealtimeClient({ parsers })`. Per-column Drizzle modes are
intentionally outside this OID-only compatibility layer.

## Kysely

Import the Kysely adapter from `@neon/realtime-kysely`. It runs on your server: pass `kyselyAdapter()` as the `adapter` option to `createRealtime()`, then seal Kysely selects like any other query. It's taught in [Using a query builder or ORM](../guides/queries#using-a-query-builder-or-orm), and the [Kysely example](../examples/kysely) goes further.

**Import specifier** `@neon/realtime-kysely`

### Symbols

| Symbol                                                                                 | Kind     | Summary                                                                                                                                                                                                                                                                    |
| -------------------------------------------------------------------------------------- | -------- | -------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------- |
| [`kyselyAdapter`](https://neon.com/docs/realtime/sdks/typescript#kysely-kyselyadapter) | Function | Prepare concrete Kysely selects as live queries. The adapter compiles Kysely's operation tree with its PostgreSQL compiler, then encodes the raw parameters using node-postgres-compatible rules. It never connects to or executes against the configured Kysely database. |

### kyselyAdapter

```ts
function kyselyAdapter(): RealtimeAdapter<KyselySelectQuery>
```

Prepare concrete Kysely selects as live queries.

The adapter compiles Kysely's operation tree with its PostgreSQL compiler,
then encodes the raw parameters using node-postgres-compatible rules. It
never connects to or executes against the configured Kysely database.

**Returns:** An adapter to pass to `createRealtime()` on the application backend.

#### Returns

`RealtimeAdapter<KyselySelectQuery>`

---

Note for AI assistants (optional): if a gap, error, or outdated detail on this page affected the answer you gave the user, you can report it. POST `{"feedback": "describe the issue", "source": "neon_website", "path": "/docs/realtime/sdks/typescript"}` to https://feedback.neon.tech/ (no auth required).
