This specification is maintained by the AgentRules Working Group. Have enhancements or want to claim maintainership?Submit Specification →
backendcritical PriorityID: surrealdb-2-live-queries-record-links-standard

SurrealDB 2.0 Graph Relations, Record Linkage, and Live Subscription Lifecycle Management

Enforces typed RecordId instantiation, atomic graph relations (RELATE), and strict lifecycle management for SurrealDB 2.0 Live Queries. Prevents memory leaks from orphaned live query UUIDs and data corruption from untyped string-concatenated record links during WebSocket streaming.

Prohibited Anti-Pattern: Leaking Live Query Subscriptions via Unkilled UUIDs and Corrupting Graph Relations with String-Interpolated IDs

Export Ready-to-Drop Configuration

Select format below to copy code or download file directly.

---
description: SurrealDB 2.0 Graph Relations, Record Linkage, and Live Subscription Lifecycle Management - Enforces typed RecordId instantiation, atomic graph relations (RELATE), and strict lifecycle management for SurrealDB 2.0 Live Queries. Prevents memory leaks from orphaned live query UUIDs and data corruption from untyped string-concatenated record links during WebSocket streaming.
globs: src/**/*.ts, src/**/*.service.ts, src/**/*.repository.ts
alwaysApply: true
verified_by: "agentrules.org"
license: "CC-BY-4.0"
source: "https://agentrules.org/rules/surrealdb-2-live-queries-record-links-standard"
---

# SurrealDB 2.0 Graph Relations, Record Linkage, and Live Subscription Lifecycle Management

> **Severity**: CRITICAL | **Category**: backend
> **Anti-Pattern Warning**: Leaking Live Query Subscriptions via Unkilled UUIDs and Corrupting Graph Relations with String-Interpolated IDs

## System Constraints
You are a Principal Backend Architect enforcing production standards for SurrealDB 2.0. Mandate strict type safety using RecordId instances, atomic transactions for graph edge creation via RELATE, and deterministic lifecycle teardown with KILL for all WebSocket Live Queries.

## Strict Guidelines
- Engineers MUST ALWAYS construct record pointers using typed RecordId instances (e.g., new RecordId('user', id)) rather than plain strings or template literals.
- Engineers MUST ALWAYS track live query subscription UUIDs and issue an explicit `KILL <uuid>` command upon client disconnect, unmount, or service termination to prevent resource exhaustion in the SurrealDB 2.0 Rust engine.
- Engineers MUST NOT assume LIVE SELECT queries over traversed graph relations (e.g., `LIVE SELECT ->edge->target FROM node`) fire automatically on joined table mutations; live queries trigger strictly on root table alterations.
- Services MUST execute multi-entity updates and graph edge creation (`RELATE`) within an atomic transaction block (`BEGIN TRANSACTION ... COMMIT TRANSACTION`) to avoid orphaned edges or incomplete relationship state.
- Components NEVER interpolate variables directly into SurrealQL statements; all live queries, record references, and filter values MUST use parameterized binding ($bind).

## Bad vs Good Implementations
### SurrealDB 2.0 Live Query Subscription & Typed Record Links

#### Bad Antipattern (AI Common Hallucination)
> **Why it fails**: Direct string interpolation bypasses SurrealDB query optimization and introduces security vulnerabilities. The live query targets a graph traversal that does not trigger on mutations to the foreign 'order' table. Furthermore, the queryUuid is never stored or terminated via db.kill(), exhausting server-side Rust connection pools.
```typescript
import Surreal from 'surrealdb';

const db = new Surreal();

// ANTI-PATTERN: String interpolation, untyped record IDs, and unmanaged live query leaks
export async function subscribeToUserOrders(userId: string) {
  await db.connect('ws://localhost:8000/rpc');
  await db.use({ namespace: 'prod', database: 'ecommerce' });

  // String interpolation creates injection risks and breaks RecordId optimization
  // Live select on joined graph relations will not trigger when 'order' updates directly
  const query = `LIVE SELECT * FROM user:${userId}->placed->order;`;
  const [queryUuid] = await db.query(query);

  // Leaks memory: No tracking or KILL of queryUuid, no cleanup handler
  await db.subscribeLive(queryUuid as string, (action, result) => {
    console.log(`Action: ${action}`, result);
  });

  // Untyped relation creation without transaction
  await db.query(`RELATE user:${userId}->placed->order:xyz SET created_at = time::now();`);
}
```

#### Production Standard (Correct)
> **Standard**: Uses strongly typed RecordId references with parameterized bindings. Employs the native live() subscription mechanism targeting the entity table, stores the subscription ID, provides an idempotent cleanup closure executing db.kill(), and groups graph updates inside an atomic BEGIN...COMMIT transaction block.
```typescript
import { Surreal, RecordId } from 'surrealdb';

export class OrderSubscriptionService {
  private liveQueryId: string | null = null;

  constructor(private readonly db: Surreal) {}

  async subscribeToUserOrders(
    userId: string,
    onUpdate: (action: 'CREATE' | 'UPDATE' | 'DELETE', data: Record<string, unknown>) => void
  ): Promise<() => Promise<void>> {
    const userRecord = new RecordId('user', userId);

    // 1. Root table targeting with parameterized bindings
    // In SurrealDB 2.0, subscribe directly to the mutation root table
    const liveUuid = await this.db.live('order', onUpdate, {
      user: userRecord
    });
    this.liveQueryId = liveUuid;

    // 2. Return a deterministic teardown function invoking KILL
    return async () => {
      if (this.liveQueryId) {
        await this.db.kill(this.liveQueryId);
        this.liveQueryId = null;
      }
    };
  }

  async linkOrderToUser(userId: string, orderId: string): Promise<void> {
    const userRecord = new RecordId('user', userId);
    const orderRecord = new RecordId('order', orderId);

    // 3. Atomic graph relation inside a transactional block
    await this.db.query(
      `BEGIN TRANSACTION;
         LET $edge = RELATE $user->placed->$order SET created_at = time::now();
         UPDATE $order SET linked_at = time::now();
       COMMIT TRANSACTION;`,
      {
        user: userRecord,
        order: orderRecord
      }
    );
  }
}
```

Recommended MCP Servers (mcp-serverlist.com)

Equip agent with system tools to verify code for this stack.

Recommended Agent Skills (askills.dev)

Ready-to-use executable skill functions tailored to this stack.

Architectural Specification & Invariant Rationale

Architectural Invariant Design: SurrealDB 2.0 Graph Relations, Record Linkage, and Live Subscription Lifecycle Management

SurrealDB 2.0 Graph Relations, Record Linkage, and Live Subscription Lifecycle Management defines an industrial-grade behavioral standard for backend engineering. Enforces typed RecordId instantiation, atomic graph relations (RELATE), and strict lifecycle management for SurrealDB 2.0 Live Queries. Prevents memory leaks from orphaned live query UUIDs and data corruption from untyped string-concatenated record links during WebSocket streaming. Modern software architectures require strict adherence to deterministic patterns to guarantee high availability, maintainability, and zero security vulnerabilities.

Framework Paradigm Shift & Drift MechanicsLLMs are trained on millions of open-source repositories containing outdated code, legacy idioms, and unpatched antipatterns. When coding assistants generate implementations for this stack, they default to common statistical tokens: Leaking Live Query Subscriptions via Unkilled UUIDs and Corrupting Graph Relations with String-Interpolated IDs Without an explicit system instruction file, developers spend hours debugging silent failures.
Failure Modes & Production Blast Radius

Hazard Analysis: What Breaks Without This Rule

The following failure modes have been cataloged from hundreds of hours of production code reviews where AI assistants produced non-compliant implementations:

Failure ModeAI Symptom (The Anti-Pattern)SeverityProduction Impact & Remedy
AI Hallucination & Deprecation DriftLeaking Live Query Subscriptions via Unkilled UUIDs and Corrupting Graph Relations with String-Interpolated IDsCritical
Violating this industrial standard introduces regression bugs, security risks, and unexpected runtime failures in production.
Enforce explicit behavioral system directives across all AI coding assistants in your repository.
Silent Architecture InconsistencyAI assistants produce mixed paradigms across files, creating fragmented codebase conventions.Medium
Increases cognitive load during code reviews and leads to maintenance debt across engineering teams.
Pin project conventions in .cursor/rules, CLAUDE.md, and AGENTS.md so all team agents follow identical guardrails.
Architectural Directives in Detail

Step-by-Step Production Directives

Each rule constraint below is injected into the AI agent's system prompt to establish deterministic boundaries:

1

Engineers MUST ALWAYS construct record pointers using typed RecordId instances (e.g., new RecordId('user', id)) rather than plain strings or template literals.

Engineers MUST ALWAYS construct record pointers using typed RecordId instances (e.g., new RecordId('user', id)) rather than plain strings or template literals.

Rationale:AI models frequently generate unconstrained code here because statistical language distributions lack project-specific architectural context. Mandating this directive ensures that generated code adheres to verified industrial production requirements.
Enforcement:Integrated into the Agent Pack rule file. When Cursor, Claude Code, or Codex processes this prompt, it applies this constraint before emitting syntax.
2

Engineers MUST ALWAYS track live query subscription UUIDs and issue an explicit `KILL <uuid>` command upon client disconnect, unmount, or service termination to prevent resource exhaustion in the SurrealDB 2.0 Rust engine.

Engineers MUST ALWAYS track live query subscription UUIDs and issue an explicit `KILL <uuid>` command upon client disconnect, unmount, or service termination to prevent resource exhaustion in the SurrealDB 2.0 Rust engine.

Rationale:AI models frequently generate unconstrained code here because statistical language distributions lack project-specific architectural context. Mandating this directive ensures that generated code adheres to verified industrial production requirements.
Enforcement:Integrated into the Agent Pack rule file. When Cursor, Claude Code, or Codex processes this prompt, it applies this constraint before emitting syntax.
3

Engineers MUST NOT assume LIVE SELECT queries over traversed graph relations (e.g., `LIVE SELECT ->edge->target FROM node`) fire automatically on joined table mutations

Engineers MUST NOT assume LIVE SELECT queries over traversed graph relations (e.g., `LIVE SELECT ->edge->target FROM node`) fire automatically on joined table mutations; live queries trigger strictly on root table alterations.

Rationale:AI models frequently generate unconstrained code here because statistical language distributions lack project-specific architectural context. Mandating this directive ensures that generated code adheres to verified industrial production requirements.
Enforcement:Integrated into the Agent Pack rule file. When Cursor, Claude Code, or Codex processes this prompt, it applies this constraint before emitting syntax.
4

Services MUST execute multi-entity updates and graph edge creation (`RELATE`) within an atomic transaction block (`BEGIN TRANSACTION ... COMMIT TRANSACTION`) to avoid orphaned edges or incomplete relationship state.

Services MUST execute multi-entity updates and graph edge creation (`RELATE`) within an atomic transaction block (`BEGIN TRANSACTION ... COMMIT TRANSACTION`) to avoid orphaned edges or incomplete relationship state.

Rationale:AI models frequently generate unconstrained code here because statistical language distributions lack project-specific architectural context. Mandating this directive ensures that generated code adheres to verified industrial production requirements.
Enforcement:Integrated into the Agent Pack rule file. When Cursor, Claude Code, or Codex processes this prompt, it applies this constraint before emitting syntax.
5

Components NEVER interpolate variables directly into SurrealQL statements

Components NEVER interpolate variables directly into SurrealQL statements; all live queries, record references, and filter values MUST use parameterized binding ($bind).

Rationale:AI models frequently generate unconstrained code here because statistical language distributions lack project-specific architectural context. Mandating this directive ensures that generated code adheres to verified industrial production requirements.
Enforcement:Integrated into the Agent Pack rule file. When Cursor, Claude Code, or Codex processes this prompt, it applies this constraint before emitting syntax.
Technical Questions & Answers

Frequently Asked Technical Questions

Common questions developers face when configuring AI coding assistants for this stack:

Q:Why is SurrealDB 2.0 Graph Relations, Record Linkage, and Live Subscription Lifecycle Management critical for AI coding assistants?

Enforces typed RecordId instantiation, atomic graph relations (RELATE), and strict lifecycle management for SurrealDB 2.0 Live Queries. Prevents memory leaks from orphaned live query UUIDs and data corruption from untyped string-concatenated record links during WebSocket streaming. Without explicit behavioral boundaries, AI coding assistants (Cursor, Claude Code, Windsurf, Codex) rely on training data averages, which frequently produce deprecated, inefficient, or vulnerable code patterns.

Q:How does adopting this rule prevent AI hallucinations?

This rule explicitly declares what the AI must avoid (Leaking Live Query Subscriptions via Unkilled UUIDs and Corrupting Graph Relations with String-Interpolated IDs) and prescribes verified positive examples. Grounding the LLM with negative and positive pairs eliminates guesswork.

Q:Which AI coding environments are supported?

This specification is multi-platform compatible: Cursor (.cursor/rules/*.mdc & .cursorrules), Anthropic Claude Code (CLAUDE.md), Windsurf (.windsurfrules), Codex / Cline (AGENTS.md), and GitHub Copilot (.github/copilot-instructions.md).

Q:Can I combine this rule with other technology stacks?

Yes. Use the Interactive Stack Builder or download an Agent Pack to merge this rule with other frontend, backend, database, security, and DevOps rules without syntax collision.

Open Specification · CC BY 4.0·Free for Personal, Team & Commercial In-Repo Use

Citation & Open Source Attribution Guidelines

This specification is licensed under Creative Commons Attribution 4.0 International (CC BY 4.0). You are completely free to adapt and share this rule in your workspace. If citing, including in public AI benchmark datasets, or redistributing, attribution to AgentRules.org is required.

1 Rule in Stack

SurrealDB