Replacing Message Brokers with SurrealDB Live Queries
Stop managing separate message brokers for real-time updates. Learn how SurrealDB's SUBSCRIBE feature pushes data changes directly to clients via WebSockets.
14 May 2026, 04:51 UTC

The Infrastructure Tax of Real-Time Updates
Building a real-time application usually requires a complex stack: a primary database for persistence, a message broker (like Redis or RabbitMQ) to handle events, and a WebSocket server to push those events to the client. This "infrastructure tax" introduces synchronization lag and multiple points of failure. If the database update succeeds but the message broker fails, your UI becomes inconsistent with your data.
SurrealDB eliminates this middle layer by treating the change feed as a first-class database feature. Using the SUBSCRIBE statement, the database itself becomes the event emitter, pushing incremental changes directly to authorized clients over WebSockets.
How the Change Feed Operates
Unlike traditional polling, where a client asks "is there new data?" every few seconds, SurrealDB uses a push model. When a client executes a SUBSCRIBE command, it opens a persistent WebSocket connection. The database then monitors the specified table for any INSERT, UPDATE, or DELETE operations.
The payload delivered to the client is not just a notification that "something changed," but the actual record state. This allows the frontend to perform immediate client-side diffing or state updates without making a follow-up API request to fetch the modified record.
Security and Access Control
A critical engineering detail is that subscriptions are not open pipes. They respect SurrealDB's built-in Access Control Lists (ACLs). If a user does not have permission to SELECT a specific record in a table, the change feed will not push that record to their subscription, preventing accidental data leaks via the real-time stream.
Worked Example: Real-Time User Presence
To implement this, you need SurrealDB v1.0+ with WebSocket support enabled. In a self-hosted environment, ensure your configuration allows WebSocket connections.
1. Setup and Data Entry
Run a SurrealDB instance via Docker and use the SurrealQL REPL to initialize your data:
# Run SurrealDB (Localhost)
docker run -p 8000:8000 surrealdb/surrealdb:latest start --user root --pass root
# In the SurrealQL REPL
CREATE TABLE users;
INSERT INTO users VALUE { name: "Alice", status: "online" };
2. Establishing the Subscription
Open a separate terminal or a JavaScript client and execute the subscription. This command tells the server to stream all changes for the users table to this specific connection:
SUBSCRIBE users;
3. Triggering the Event
While the subscription is active, perform an update in your primary terminal:
UPDATE users SET status = "away" WHERE name = "Alice";
The subscribing client will immediately receive a JSON payload containing the updated record and the operation type (UPDATE), allowing the UI to toggle the status indicator instantly.
Engineering Trade-offs and Limitations
While removing a message broker simplifies the architecture, it shifts the load to the database's network layer. Consider these constraints:
- Connection Saturation: Each subscription is a persistent WebSocket. In extremely high-volume environments, a single connection can become a bottleneck. If you are streaming thousands of updates per second to a single client, consider partitioning your tables or filtering the subscription.
- Client-Side State: SurrealDB provides the current state of the record, but the client is responsible for reconnection logic. If the WebSocket closes, the client must re-subscribe and potentially fetch a snapshot of the data to fill the gap during the downtime.
- Bandwidth: Because the full record is sent on every change, large documents can lead to high bandwidth consumption. Keep your real-time tables lean.
Verifying the Implementation
To verify your real-time feed is functioning correctly, check the following:
- Connection Check: Ensure the WebSocket handshake completes (HTTP 101 Switching Protocols).
- Latency Test: Perform an update via the HTTP API and measure the time until the
SUBSCRIBEclient receives the payload. - Permission Test: Attempt to subscribe to a table using a user account that lacks
SELECTpermissions; the server should not push records to that client.
0 replies
A thoughtful contribution can make all the difference. Be the first to share one.