Live Query Promises Live query promises provide interfaces for subscribing to real-time updates from SurrealDB. There are two variants: ManagedLivePromise for new subscriptions and UnmanagedLivePromise for existing ones.
Returned by: SurrealQueryable.live() , SurrealQueryable.liveOf()
Source: query/live.ts
ManagedLivePromise<T>A managed live query subscription that the SDK automatically creates and manages.
Returned by: SurrealQueryable.live()
Configuration Methods .diff()Configure the subscription to return only patches (diffs) instead of full records on updates.
Returns: ManagedLivePromise<T> - Chainable promise
Example:
const subscription = await db . live ( new Table ( 'users' ) ) . diff ( ) ; for await ( const update of subscription ) { console . log ( 'Diff:' , update . diff ) ; // Only changed fields }
.fields()Select only specific fields in the live updates.
livePromise . fields ( ... fields ) Parameters:
Parameter Type Description fields Field<T>[]Field names to include in updates.
Returns: ManagedLivePromise<T>
Example:
const subscription = await db . live ( new Table ( 'users' ) ) . fields ( 'name' , 'email' , 'status' ) ; for await ( const update of subscription ) { // Only includes specified fields console . log ( update . result ) ; // { name, email, status } }
.value()Return only the value of a specific field in updates.
Parameters:
Parameter Type Description field Field<T>Field name to extract.
Returns: ManagedLivePromise<T>
Example:
const subscription = await db . live ( new Table ( 'users' ) ) . value ( 'name' ) ; for await ( const update of subscription ) { console . log ( 'Name changed:' , update . result ) ; // Just the name string }
.where()Filter live updates to only receive records matching the condition.
livePromise . where ( condition ) Parameters:
Parameter Type Description condition ExprLikeCondition expression to filter updates (string or Expression object).
Returns: ManagedLivePromise<T>
Example:
const subscription = await db . live ( new Table ( 'users' ) ) . where ( 'age >= 18' ) ; for await ( const update of subscription ) { // Only receives updates for users with age >= 18 console . log ( update . action , update . result ) ; }
.fetch()Fetch related records in live updates.
livePromise . fetch ( ... fields ) Parameters:
Parameter Type Description fields Field<T>[]Related fields to fetch.
Returns: ManagedLivePromise<T>
Example:
const subscription = await db . live ( new Table ( 'posts' ) ) . fetch ( 'author' , 'comments' ) ; for await ( const update of subscription ) { // author and comments are fully populated console . log ( 'Post by:' , update . result . author . name ) ; }
Live Subscription Methods Once awaited, a ManagedLivePromise returns a LiveSubscription object:
Iteration for await ( const update of subscription ) { console . log ( update . action ) ; // 'CREATE' | 'UPDATE' | 'DELETE' console . log ( update . result ) ; // The record data } .kill()Kill the live query subscription.
await subscription . kill ( ) ; UnmanagedLivePromiseAn unmanaged subscription to an existing live query by its UUID.
Returned by: SurrealQueryable.liveOf()
Usage const liveQueryId : Uuid = /* from somewhere */ ; const subscription = await db . liveOf ( liveQueryId ) ; for await ( const update of subscription ) { console . log ( update ) ; } Complete Examples Basic Live Query import { Surreal , Table } from 'surrealdb' ; const db = new Surreal ( ) ; await db . connect ( 'ws://localhost:8000' ) ; // Subscribe to all user changes const subscription = await db . live ( new Table ( 'users' ) ) ; for await ( const update of subscription ) { console . log ( ` ${ update . action } :` , update . result ) ; } // Clean up when done await subscription . kill ( ) ; Filtered Live Query // Only receive updates for active users const subscription = await db . live ( new Table ( 'users' ) ) . where ( 'status = "active"' ) ; for await ( const update of subscription ) { if ( update . action === 'CREATE' ) { console . log ( 'New active user:' , update . result ) ; } else if ( update . action === 'UPDATE' ) { console . log ( 'Active user updated:' , update . result ) ; } else if ( update . action === 'DELETE' ) { console . log ( 'Active user deleted:' , update . result ) ; } } Live Query with Specific Fields const subscription = await db . live ( new Table ( 'users' ) ) . fields ( 'name' , 'email' , 'status' ) . where ( 'role = "admin"' ) ; for await ( const update of subscription ) { // Only receives name, email, status fields console . log ( 'Admin update:' , update . result ) ; } await subscription . kill ( ) ; Diff-Based Updates // Get only changes, not full records const subscription = await db . live ( new Table ( 'users' ) ) . diff ( ) ; for await ( const update of subscription ) { if ( update . action === 'UPDATE' ) { console . log ( 'Changed fields:' , update . diff ) ; // { email: 'new@example.com' } instead of full record } } Live Query with Relations const subscription = await db . live ( new Table ( 'posts' ) ) . fetch ( 'author' , 'comments' ) . where ( 'published = true' ) ; for await ( const update of subscription ) { // author is fully populated console . log ( 'Post by:' , update . result . author . name ) ; console . log ( 'Comments:' , update . result . comments . length ) ; } Real-time Dashboard async function monitorUsers ( callback : ( stats : any ) => void ) { const subscription = await db . live ( new Table ( 'users' ) ) ; const stats = { created : 0 , updated : 0 , deleted : 0 } ; for await ( const update of subscription ) { if ( update . action === 'CREATE' ) stats . created ++ ; else if ( update . action === 'UPDATE' ) stats . updated ++ ; else if ( update . action === 'DELETE' ) stats . deleted ++ ; callback ( stats ) ; } } monitorUsers ( ( stats ) => { console . log ( 'User stats:' , stats ) ; } ) ; Watch Specific Record // Subscribe to changes on a specific record const subscription = await db . live ( new RecordId ( 'users' , 'john' ) ) ; for await ( const update of subscription ) { if ( update . action === 'UPDATE' ) { console . log ( 'John was updated:' , update . result ) ; } else if ( update . action === 'DELETE' ) { console . log ( 'John was deleted' ) ; break ; } } Auto-reconnect Live Query let subscription : LiveSubscription | null = null ; async function setupLiveQuery ( ) { subscription = await db . live ( new Table ( 'users' ) ) . where ( 'active = true' ) ; for await ( const update of subscription ) { console . log ( 'Update:' , update ) ; } } // Handle reconnection db . subscribe ( 'reconnecting' , ( ) => { console . log ( 'Connection lost, live query will be restored...' ) ; } ) ; db . subscribe ( 'connected' , async ( ) => { console . log ( 'Reconnected, live queries restored automatically' ) ; } ) ; await setupLiveQuery ( ) ; Cleanup Pattern const subscriptions : LiveSubscription [ ] = [ ] ; // Create multiple subscriptions subscriptions . push ( await db . live ( new Table ( 'users' ) ) ) ; subscriptions . push ( await db . live ( new Table ( 'posts' ) ) ) ; subscriptions . push ( await db . live ( new Table ( 'comments' ) ) ) ; // Process updates // ... // Cleanup all subscriptions async function cleanup ( ) { await Promise . all ( subscriptions . map ( sub => sub . kill ( ) ) ) ; console . log ( 'All subscriptions cleaned up' ) ; } // Call on app shutdown await cleanup ( ) ; Error Handling try { const subscription = await db . live ( new Table ( 'users' ) ) ; try { for await ( const update of subscription ) { await processUpdate ( update ) ; } } catch ( error ) { console . error ( 'Error processing update:' , error ) ; } finally { await subscription . kill ( ) ; } } catch ( error ) { if ( error instanceof LiveSubscriptionError ) { console . error ( 'Failed to create subscription:' , error ) ; } } Update Message Structure Each update message conforms to the LiveMessage<T> interface with action, result, and optional diff properties.
Processing Updates for await ( const update of subscription ) { switch ( update . action ) { case 'CREATE' : await handleCreate ( update . result ) ; break ; case 'UPDATE' : await handleUpdate ( update . result , update . diff ) ; break ; case 'DELETE' : await handleDelete ( update . result ) ; break ; } } See Also