From 3e67b3628a6831d1a3f74f5f6e4f60ee592e4220 Mon Sep 17 00:00:00 2001
From: sepcnt <30561671+sepcnt@users.noreply.github.com>
Date: Wed, 1 Apr 2026 20:54:56 +0800
Subject: [PATCH] [world] Add workflow-world-surrealdb
Signed-off-by: sepcnt <30561671+sepcnt@users.noreply.github.com>
---
.../workflows/benchmark-community-world.yml | 16 ++
.github/workflows/e2e-community-world.yml | 16 ++
docs/content/docs/deploying/world/meta.json | 2 +-
.../docs/deploying/world/surrealdb-world.mdx | 251 ++++++++++++++++++
scripts/create-community-worlds-matrix.mjs | 4 +-
worlds-manifest.json | 32 +++
6 files changed, 318 insertions(+), 3 deletions(-)
create mode 100644 docs/content/docs/deploying/world/surrealdb-world.mdx
diff --git a/.github/workflows/benchmark-community-world.yml b/.github/workflows/benchmark-community-world.yml
index 8dbd003dc0..b40eaca553 100644
--- a/.github/workflows/benchmark-community-world.yml
+++ b/.github/workflows/benchmark-community-world.yml
@@ -86,6 +86,21 @@ jobs:
sleep 2
done
+ - name: Start SurrealDB
+ if: ${{ inputs.service-type == 'surrealdb' }}
+ run: |
+ docker run -d --name surrealdb -p 8000:8000 \
+ surrealdb/surrealdb:v3 \
+ start --user root --pass root --bind 0.0.0.0:8000 memory
+ echo "Waiting for SurrealDB to be ready..."
+ for i in {1..30}; do
+ if curl -sf http://localhost:8000/health &>/dev/null; then
+ echo "SurrealDB is ready"
+ break
+ fi
+ sleep 2
+ done
+
- name: Setup environment
uses: ./.github/actions/setup-workflow-dev
with:
@@ -143,3 +158,4 @@ jobs:
run: |
docker stop mongodb 2>/dev/null || true
docker stop redis 2>/dev/null || true
+ docker stop surrealdb 2>/dev/null || true
diff --git a/.github/workflows/e2e-community-world.yml b/.github/workflows/e2e-community-world.yml
index 0048eed477..1d5f53426c 100644
--- a/.github/workflows/e2e-community-world.yml
+++ b/.github/workflows/e2e-community-world.yml
@@ -82,6 +82,21 @@ jobs:
sleep 2
done
+ - name: Start SurrealDB
+ if: ${{ inputs.service-type == 'surrealdb' }}
+ run: |
+ docker run -d --name surrealdb -p 8000:8000 \
+ surrealdb/surrealdb:v3 \
+ start --user root --pass root --bind 0.0.0.0:8000 memory
+ echo "Waiting for SurrealDB to be ready..."
+ for i in {1..30}; do
+ if curl -sf http://localhost:8000/health &>/dev/null; then
+ echo "SurrealDB is ready"
+ break
+ fi
+ sleep 2
+ done
+
- name: Setup environment
uses: ./.github/actions/setup-workflow-dev
with:
@@ -135,3 +150,4 @@ jobs:
run: |
docker stop mongodb 2>/dev/null || true
docker stop redis 2>/dev/null || true
+ docker stop surrealdb 2>/dev/null || true
diff --git a/docs/content/docs/deploying/world/meta.json b/docs/content/docs/deploying/world/meta.json
index 0cb3e7c432..1cbc2b1991 100644
--- a/docs/content/docs/deploying/world/meta.json
+++ b/docs/content/docs/deploying/world/meta.json
@@ -1,4 +1,4 @@
{
"title": "World",
- "pages": ["local-world", "vercel-world", "postgres-world"]
+ "pages": ["local-world", "vercel-world", "postgres-world", "surrealdb-world"]
}
diff --git a/docs/content/docs/deploying/world/surrealdb-world.mdx b/docs/content/docs/deploying/world/surrealdb-world.mdx
new file mode 100644
index 0000000000..7ef055d90d
--- /dev/null
+++ b/docs/content/docs/deploying/world/surrealdb-world.mdx
@@ -0,0 +1,251 @@
+---
+title: SurrealDB World
+description: Community world using SurrealDB with LIVE SELECT for queueing and real-time streaming.
+type: integration
+summary: Deploy workflows to your own infrastructure using SurrealDB.
+prerequisites:
+ - /docs/deploying
+related:
+ - /docs/deploying/world/local-world
+ - /docs/deploying/world/postgres-world
+---
+
+The SurrealDB World is a community-maintained backend for self-hosted deployments. It uses [SurrealDB](https://surrealdb.com) for durable storage and leverages `LIVE SELECT` for reactive queue processing and real-time streaming.
+
+Use the SurrealDB World when you want a single-binary database that handles storage, queuing, and streaming without additional infrastructure like a separate job queue.
+
+
+This is a community world maintained at [sepcnt/workflow-world-surrealdb](https://github.com/sepcnt/workflow-world-surrealdb). For bug reports and feature requests, please use that repository.
+
+
+## Installation
+
+Install the SurrealDB World package in your workflow project:
+
+```package-install
+workflow-world-surrealdb
+```
+
+Configure the required environment variables:
+
+```bash title=".env"
+WORKFLOW_TARGET_WORLD="workflow-world-surrealdb"
+WORKFLOW_SURREAL_URL="ws://127.0.0.1:8000/rpc"
+WORKFLOW_SURREAL_NAMESPACE="workflow"
+WORKFLOW_SURREAL_DATABASE="workflow"
+WORKFLOW_SURREAL_USERNAME="root"
+WORKFLOW_SURREAL_PASSWORD="root"
+```
+
+Run the setup script to create the necessary tables and functions in your database:
+
+```bash
+npx workflow-surreal-setup
+```
+
+
+The setup is idempotent and can safely be run as a post-deployment lifecycle script.
+
+
+## Running SurrealDB
+
+Start a SurrealDB instance using Docker:
+
+```bash
+docker run -d -p 8000:8000 \
+ surrealdb/surrealdb:v3 \
+ start --user root --pass root --bind 0.0.0.0:8000 memory
+```
+
+Or use the included `docker-compose.yml`:
+
+```bash
+docker compose up -d
+```
+
+For persistent storage, replace `memory` with a file path:
+
+```bash
+docker run -d -p 8000:8000 -v surrealdb-data:/data \
+ surrealdb/surrealdb:v3 \
+ start --user root --pass root --bind 0.0.0.0:8000 \
+ "surrealkv:///data/workflow.db?versioned=true"
+```
+
+## Starting the World
+
+To subscribe to the queue via LIVE SELECT, your workflow app needs to start the world on server start. Here are examples for a few frameworks:
+
+
+
+
+
+Create an `instrumentation.ts` file in your project root:
+
+```ts title="instrumentation.ts" lineNumbers
+export async function register() {
+ if (process.env.NEXT_RUNTIME !== "edge") {
+ const { getWorld } = await import("workflow/runtime");
+ await getWorld().start?.();
+ }
+}
+```
+
+
+Learn more about [Next.js Instrumentation](https://nextjs.org/docs/app/guides/instrumentation).
+
+
+
+
+
+
+Create a `src/hooks.server.ts` file:
+
+```ts title="src/hooks.server.ts" lineNumbers
+import type { ServerInit } from "@sveltejs/kit";
+
+export const init: ServerInit = async () => {
+ const { getWorld } = await import("workflow/runtime");
+ await getWorld().start?.();
+};
+```
+
+
+Learn more about [SvelteKit Hooks](https://svelte.dev/docs/kit/hooks).
+
+
+
+
+
+
+Create a plugin to start the world on server initialization:
+
+```ts title="plugins/start-surreal-world.ts" lineNumbers
+import { defineNitroPlugin } from "nitro/~internal/runtime/plugin";
+
+export default defineNitroPlugin(async () => {
+ const { getWorld } = await import("workflow/runtime");
+ await getWorld().start?.();
+});
+```
+
+Register the plugin in your config:
+
+```ts title="nitro.config.ts"
+import { defineNitroConfig } from "nitropack";
+
+export default defineNitroConfig({
+ modules: ["workflow/nitro"],
+ plugins: ["plugins/start-surreal-world.ts"],
+});
+```
+
+
+Learn more about [Nitro Plugins](https://v3.nitro.build/docs/plugins).
+
+
+
+
+
+
+
+The SurrealDB World requires a long-lived worker process that maintains LIVE SELECT subscriptions. This does not work on serverless environments. For Vercel deployments, use the [Vercel World](/worlds/vercel) instead.
+
+
+## Configuration
+
+All configuration options can be set via environment variables or programmatically via `createWorld()`.
+
+### `WORKFLOW_SURREAL_URL`
+
+SurrealDB WebSocket URL. Supports `ws://`, `wss://`, `http://`, and `https://` protocols (HTTP is auto-converted to WS).
+
+Default: `ws://127.0.0.1:8000/rpc`
+
+### `WORKFLOW_SURREAL_NAMESPACE`
+
+SurrealDB namespace. Default: `workflow`
+
+### `WORKFLOW_SURREAL_DATABASE`
+
+SurrealDB database. Default: `workflow`
+
+### `WORKFLOW_SURREAL_USERNAME` / `WORKFLOW_SURREAL_PASSWORD`
+
+Root or namespace-level credentials for authentication.
+
+### `WORKFLOW_SURREAL_TOKEN`
+
+Alternative to username/password. Use a JWT token for authentication.
+
+### `WORKFLOW_SURREAL_QUEUE_CONCURRENCY`
+
+Number of concurrent jobs to process. Default: `10`
+
+### `WORKFLOW_SURREAL_QUEUE_LANE_SHARDS`
+
+Number of queue lane partitions for horizontal scalability. Default: `16`
+
+### `WORKFLOW_SURREAL_QUEUE_LEASE_MS`
+
+Job lease duration in milliseconds before a job is considered stale. Default: `300000` (5 minutes)
+
+### `WORKFLOW_SURREAL_QUEUE_HEARTBEAT_MS`
+
+Heartbeat interval for extending job leases. Default: `10000` (10 seconds)
+
+### Programmatic configuration
+
+{/* @skip-typecheck: incomplete code sample */}
+```typescript title="workflow.config.ts" lineNumbers
+import { createWorld } from "workflow-world-surrealdb";
+
+const world = createWorld({
+ url: "ws://127.0.0.1:8000/rpc",
+ namespace: "workflow",
+ database: "workflow",
+ auth: {
+ username: "root",
+ password: "root",
+ },
+ queueConcurrency: 20,
+ queueLaneShards: 32,
+});
+```
+
+## How It Works
+
+The SurrealDB World uses SurrealDB as a unified backend:
+
+- **Storage** — Workflow runs, events, steps, and hooks are stored in SurrealDB tables with SCHEMAFULL validation
+- **Job Queue** — Lane-sharded queue with `LIVE SELECT` subscriptions for instant wake-up and automatic lease recovery
+- **Streaming** — `LIVE SELECT` on stream chunk tables enables real-time event distribution with periodic reconciliation
+
+This architecture keeps the infrastructure minimal — a single SurrealDB instance handles storage, queuing, and streaming without additional services. For implementation details, see the [source code](https://github.com/sepcnt/workflow-world-surrealdb).
+
+## Deployment
+
+Deploy your application to any cloud that supports long-running servers:
+
+- Docker containers
+- Kubernetes clusters
+- Virtual machines
+- Platform-as-a-Service providers (Railway, Render, Fly.io, etc.)
+
+Ensure your deployment has:
+1. Network access to your SurrealDB instance
+2. Environment variables configured correctly
+3. The `start()` function called on server initialization
+
+
+The SurrealDB World is not compatible with Vercel deployments. On Vercel, workflows automatically use the [Vercel World](/worlds/vercel) with zero configuration.
+
+
+## Limitations
+
+- **Requires long-running process** — Must call `start()` on server initialization; not compatible with serverless platforms
+- **SurrealDB infrastructure** — Requires a SurrealDB instance (self-hosted or [Surreal Cloud](https://surrealdb.com/cloud))
+- **Not compatible with Vercel** — Use the [Vercel World](/worlds/vercel) for Vercel deployments
+- **Community-maintained** — Not an official Vercel package; support via [GitHub Issues](https://github.com/sepcnt/workflow-world-surrealdb/issues)
+
+For local development, use the [Local World](/worlds/local) which requires no external services.
diff --git a/scripts/create-community-worlds-matrix.mjs b/scripts/create-community-worlds-matrix.mjs
index 75b3aec8b1..0efdbbb02b 100644
--- a/scripts/create-community-worlds-matrix.mjs
+++ b/scripts/create-community-worlds-matrix.mjs
@@ -50,9 +50,9 @@ const matrix = {
let serviceType = 'none';
if (world.services && world.services.length > 0) {
// Use the first service's name as the service type
- // Currently supports: mongodb, redis
+ // Currently supports: mongodb, redis, surrealdb
const serviceName = world.services[0].name;
- if (['mongodb', 'redis'].includes(serviceName)) {
+ if (['mongodb', 'redis', 'surrealdb'].includes(serviceName)) {
serviceType = serviceName;
}
}
diff --git a/worlds-manifest.json b/worlds-manifest.json
index 4e72dc0174..4517508a53 100644
--- a/worlds-manifest.json
+++ b/worlds-manifest.json
@@ -129,6 +129,38 @@
}
]
},
+ {
+ "id": "surrealdb",
+ "type": "community",
+ "package": "workflow-world-surrealdb",
+ "name": "SurrealDB",
+ "description": "SurrealDB world using LIVE SELECT for queueing and real-time streaming",
+ "repository": "https://github.com/sepcnt/workflow-world-surrealdb",
+ "docs": "/docs/deploying/world/surrealdb-world",
+ "features": [],
+ "env": {
+ "WORKFLOW_TARGET_WORLD": "workflow-world-surrealdb",
+ "WORKFLOW_SURREAL_URL": "ws://127.0.0.1:8000/rpc",
+ "WORKFLOW_SURREAL_NAMESPACE": "workflow",
+ "WORKFLOW_SURREAL_DATABASE": "workflow",
+ "WORKFLOW_SURREAL_USERNAME": "root",
+ "WORKFLOW_SURREAL_PASSWORD": "root"
+ },
+ "services": [
+ {
+ "name": "surrealdb",
+ "image": "surrealdb/surrealdb:v3",
+ "ports": ["8000:8000"],
+ "healthCheck": {
+ "cmd": "curl -sf http://localhost:8000/health || exit 1",
+ "interval": "5s",
+ "timeout": "3s",
+ "retries": 10
+ }
+ }
+ ],
+ "setup": "pnpm exec workflow-surreal-setup"
+ },
{
"id": "jazz",
"type": "community",