SurrealDB
A multi-model cloud-native database with a SQL-like query language, real-time subscriptions, and a single binary that runs embedded or as a server.
SurrealDB is a multi-model database written in Rust that can run as a standalone server, be embedded directly into your application, or deployed to the cloud. It supports document, graph, relational, and time-series data in a single engine, queried with SurrealQL — a familiar SQL-like language extended with graph traversal, geospatial queries, and real-time change feeds.
Features
- Multi-model — store and query documents, related records (graph edges), and time-series data all in one database, without stitching together multiple systems
- SurrealQL — a rich query language that looks like SQL but adds record
links, graph traversal (
->,<-), destructuring, and first-class support for nested objects and arrays - Real-time subscriptions —
LIVE SELECTqueries push changes to connected clients over WebSocket as they happen - Single binary — the
surrealCLI starts a full database server, runs an embedded in-process database, or launches an interactive REPL — no separate installation steps - Schemaless or schemafull — define strict schemas with
DEFINE TABLE ... SCHEMAFULLor go fully schemaless; mix both in the same database - Fine-grained permissions — row-level access control defined directly in the schema using SurrealQL expressions
- Multi-tenancy — first-class namespaces and databases allow clean separation of tenants within a single server instance
- Embedded mode — embed SurrealDB directly into a Rust application using the
surrealdbcrate, with the same query API as the server - Multiple storage backends — in-memory, RocksDB (persistent), TiKV (distributed), and SurrealKV
Installation
Download a pre-built binary from the official website:
# Debian / Ubuntu / Fedora
# No apt or dnf package is available. Use the official install script (works on all Linux distributions):
curl -sSf https://install.surrealdb.com | sh
# macOS (Homebrew alternative — install script)
curl -sSf https://install.surrealdb.com | sh
# macOS (Homebrew)
brew install surrealdb/tap/surreal
# Windows (scoop)
scoop bucket add surrealdb https://github.com/surrealdb/scoop.git
scoop install surreal
# cargo
cargo install surrealdb-cliStarting a server
# Start an in-memory server (data lost on restart — good for development)
surreal start --log debug --user root --pass root memory
# Start a persistent server backed by RocksDB
surreal start --log info --user root --pass root file:///data/mydb
# Start on a custom bind address and port
surreal start --bind 0.0.0.0:8000 --user root --pass root memoryInteractive REPL
# Connect to a running server and open an interactive SQL shell
surreal sql --conn http://localhost:8000 --user root --pass root --ns myns --db mydbSurrealQL Examples
-- Create a record (document-style)
CREATE person:alice SET
name = 'Alice',
age = 30,
tags = ['rust', 'databases'];
-- Select with filtering
SELECT name, age FROM person WHERE age > 25 ORDER BY age;
-- Graph relationships — connect two records with an edge
RELATE person:alice -> knows -> person:bob
SET since = time::now();
-- Traverse the graph
SELECT ->(knows)->person.name AS friends FROM person:alice;
-- Live query — subscribe to real-time changes
LIVE SELECT * FROM orders WHERE status = 'pending';
-- Define a schemafull table with permissions
DEFINE TABLE post SCHEMAFULL
PERMISSIONS
FOR select WHERE published = true OR author = $auth.id
FOR create, update WHERE author = $auth.id
FOR delete WHERE author = $auth.id;
DEFINE FIELD title ON post TYPE string;
DEFINE FIELD body ON post TYPE string;
DEFINE FIELD author ON post TYPE record(person);
DEFINE FIELD published ON post TYPE bool DEFAULT false;Embedded usage in Rust
use surrealdb::Surreal;
use surrealdb::engine::local::Mem;
#[tokio::main]
async fn main() -> surrealdb::Result<()> {
// Open an in-process in-memory database
let db = Surreal::new::<Mem>(()).await?;
db.use_ns("myapp").use_db("production").await?;
// Insert a record
let _: Vec<serde_json::Value> = db
.create("person")
.content(serde_json::json!({ "name": "Alice", "age": 30 }))
.await?;
// Query it back
let people: Vec<serde_json::Value> = db
.query("SELECT * FROM person WHERE age > 25")
.await?
.take(0)?;
println!("{people:#?}");
Ok(())
}Export and import
# Export a database to a SurrealQL file
surreal export --conn http://localhost:8000 --user root --pass root \
--ns myns --db mydb backup.surql
# Import a SurrealQL file into a database
surreal import --conn http://localhost:8000 --user root --pass root \
--ns myns --db mydb backup.surql