Skip to content
NEW BLOG

Using Surrealism to build your own extensions

Read blog

1/2

Extensions illustration

Extensions

Run custom logic inside SurrealDB. Write functions in Rust, compile to WebAssembly, and execute with full query engine access - no microservices, no cold starts, no network hops.

Run extensions inside SurrealDB

SurrealDB extensions turn it into a programmable data and logic layer - perfect for agentic and AI-heavy workloads

WASM SANDBOXING

Isolated by design

Each module call creates a fresh WASM instance with its own isolated memory. Modules can only interact with SurrealDB through explicit host functions - no filesystem, no raw network, no direct database access. Data crosses the boundary via serialisation.

SurrealDB

SurrealDB Engine

Query engine

Parses and executes SurrealQL

Transaction context

Shared ACID boundary

Host bridge

WASM Sandbox

Module code

User-defined Rust compiled to WASM

Isolated memory

Own Store and Instance per call

No filesystem

No direct DB

No raw network

BUILD PIPELINE

How extensions work

Write your functions in Rust, compile into WebAssembly with the SurrealDB CLI, load them into your instance, and call them from SurrealQL.

1

Functions

fn return_ten() -> i32 { 10 }

fn is_positive(n: i32) -> bool { n >= 0 }

Use #[surrealism] to expose functions

#[surrealism]

fn return_ten() -> i32 { 10 }

#[surrealism]

fn is_positive(n: i32) -> bool { n >= 0 }

surrealism.toml

[package]

organisation = "surrealdb"

name = "demo"

version = "1.0.0"

2

Compile with SurrealDB CLI

surreal module

command

Rust code ready

to compile to WASM

Compiled Surrealism

module

3

SurrealDB instance

Create file location with

DEFINE BUCKET

Access compiled Surrealism module with

DEFINE MODULE

4

Access functions inside SurrealDB

CREATE person

SET num = mod::test::return_ten();

SELECT

id,

mod::test::is_positive(num)

AS is_positive

FROM person;

TRANSACTION SAFETY

Same transaction, same commit

When a module calls back into SurrealQL via the host bridge, it runs in the same transaction context as the query that invoked it. Module writes, host callbacks, and the original query all commit or roll back as a single atomic unit. No eventual-consistency bugs.

CREATE person SET score = mod::ml::predict(data);

Single ACID transaction

Query engine

Parses SurrealQL, finds mod:: call

WASM module executes

mod::ml::predict() runs in sandbox

Host callback

__sr_sql("SELECT * FROM training_data")

Runs in same ctx and opt - same transaction

Result returned

Module returns prediction, query continues

COMMIT

Query + module writes + host callbacks - one atomic unit

ZERO-DOWNTIME UPGRADES

Hot-load, no downtime

Deploy, upgrade, or roll back modules without restarting your instance. In-flight requests continue on the previous version while new requests automatically load the updated module from storage. No forced termination, no cold starts.

DEFINE MODULE OVERWRITE ml;

Cache invalidation

cache.remove(&lookup) - evicts the compiled Runtime

In-flight requests

Continue on Module v1

Arc<Runtime> stays valid

Complete normally

Old runtime dropped when done

New requests

Cache miss → load from bucket

Build new Runtime, cache it

Module v2 live

Zero downtime transition

GET STARTED

Start building extensions

Run AI and application logic inside SurrealDB with WebAssembly extensions