• Start

Languages

/

JavaScript

/

API Reference

/

Query builders

LivePromise

LivePromise variants for managing real-time live query subscriptions.

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

A managed live query subscription that the SDK automatically creates and manages.

Returned by: SurrealQueryable.live()

Configure the subscription to return only patches (diffs) instead of full records on updates.

Method Syntax
livePromise.diff()

**Returns:** `ManagedLivePromise` - 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
}

Select only specific fields in the live updates.

Method Syntax
livePromise.fields(...fields)

Parameters:

Parameter

Type

Description

fieldsField<T>[]

Field names to include in updates.

**Returns:** `ManagedLivePromise`

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 }
}

Return only the value of a specific field in updates.

Method Syntax
livePromise.value(field)

Parameters:

Parameter

Type

Description

fieldField<T>

Field name to extract.

**Returns:** `ManagedLivePromise`

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
}

Filter live updates to only receive records matching the condition.

Method Syntax
livePromise.where(expr)

Parameters:

Parameter

Type

Description

exprExprLike

Condition expression to filter updates (string or

Expression

object).

**Returns:** `ManagedLivePromise`

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 related records in live updates.

Method Syntax
livePromise.fetch(...fields)

Parameters:

Parameter

Type

Description

fieldsField<T>[]

Related fields to fetch.

**Returns:** `ManagedLivePromise`

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);
}

Compile the query into a BoundQuery.

Method Syntax
livePromise.compile()

Returns: BoundQuery - The compiled query

Once awaited, a ManagedLivePromise returns a LiveSubscription object:

for await (const update of subscription) {
    console.log(update.action); // 'CREATE' | 'UPDATE' | 'DELETE'
    console.log(update.result); // The record data
}

Kill the live query subscription.

await subscription.kill();

An unmanaged subscription to an existing live query by its UUID.

Returned by: SurrealQueryable.liveOf()

const liveQueryId: Uuid = /* from somewhere */;
const subscription = await db.liveOf(liveQueryId);

for await (const update of subscription) {
    console.log(update);
}
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();
// 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);
    }
}
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();
// 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
    }
}
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);
}
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);
});
// 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;
    }
}
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();
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();
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);
    }
}

Each update message conforms to the [`LiveMessage`](/docs/languages/javascript/api/types/#livemessage) interface with `action`, `result`, and optional `diff` properties.

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;
    }
}

Was this page helpful?