DEV Community

Alex Spinov
Alex Spinov

Posted on

SurrealDB Has a Free API — SQL + Document + Graph in One Database

SurrealDB is the multi-model database that combines SQL, document, graph, and time-series — one database to replace PostgreSQL + MongoDB + Neo4j. Free and open source.

Why SurrealDB?

  • Multi-model — relational + document + graph in one DB
  • SurrealQL — SQL-like query language with graph traversal
  • Real-time — live queries via WebSocket
  • Auth built-in — row-level security, JWT, scopes
  • Serverless — runs embedded, as server, or in-browser (WASM)
  • HTTP & WebSocket API — no driver needed

Quick Start

# Install
curl -sSf https://install.surrealdb.com | sh

# Start server
surreal start --user root --pass root memory
# or with file storage:
surreal start --user root --pass root file:mydata.db

# Connect via CLI
surreal sql --conn http://localhost:8000 --user root --pass root --ns test --db test
Enter fullscreen mode Exit fullscreen mode

CRUD Operations

-- Create records (schemaless by default)
CREATE user SET
  name = 'Alice',
  email = 'alice@example.com',
  age = 30,
  skills = ['TypeScript', 'React', 'Node.js'];

-- Create with specific ID
CREATE user:bob SET
  name = 'Bob',
  email = 'bob@example.com',
  age = 25;

-- Query
SELECT * FROM user WHERE age > 25;
SELECT name, email FROM user WHERE skills CONTAINS 'React';

-- Update
UPDATE user:bob SET age = 26, role = 'admin';

-- Delete
DELETE user:bob;
Enter fullscreen mode Exit fullscreen mode

Graph Relations (The Killer Feature)

-- Create users
CREATE user:alice SET name = 'Alice';
CREATE user:bob SET name = 'Bob';
CREATE user:charlie SET name = 'Charlie';

-- Create graph relations
RELATE user:alice->follows->user:bob SET since = '2024-01-15';
RELATE user:bob->follows->user:charlie SET since = '2024-03-20';
RELATE user:charlie->follows->user:alice SET since = '2024-06-01';

-- Traverse the graph!
SELECT ->follows->user.name FROM user:alice;
-- Returns: ['Bob']

-- Two-hop traversal (friends of friends)
SELECT ->follows->user->follows->user.name FROM user:alice;
-- Returns: ['Charlie']

-- Reverse traversal (who follows Alice?)
SELECT <-follows<-user.name FROM user:alice;
-- Returns: ['Charlie']
Enter fullscreen mode Exit fullscreen mode

No separate graph database. No joins. Just arrows.

JavaScript Client

npm install surrealdb
Enter fullscreen mode Exit fullscreen mode
import Surreal from "surrealdb";

const db = new Surreal();
await db.connect("http://localhost:8000/rpc");
await db.use({ namespace: "test", database: "test" });
await db.signin({ username: "root", password: "root" });

// Create
const user = await db.create("user", {
  name: "Alice",
  email: "alice@example.com",
  age: 30,
});

// Select all
const users = await db.select("user");

// Query
const results = await db.query(
  "SELECT * FROM user WHERE age > $minAge",
  { minAge: 25 }
);

// Live query (real-time updates!)
const stream = await db.live("user");
stream.subscribe((action, result) => {
  console.log(`${action}: ${JSON.stringify(result)}`);
});
Enter fullscreen mode Exit fullscreen mode

Live Queries (Real-Time)

// Subscribe to changes on a table
const queryUuid = await db.live("user", (action, result) => {
  switch (action) {
    case "CREATE":
      console.log("New user:", result);
      break;
    case "UPDATE":
      console.log("User updated:", result);
      break;
    case "DELETE":
      console.log("User deleted:", result);
      break;
  }
});

// When done:
await db.kill(queryUuid);
Enter fullscreen mode Exit fullscreen mode

Auth & Permissions (Built-in!)

-- Define a scope (authentication layer)
DEFINE SCOPE user SESSION 24h
  SIGNUP (
    CREATE user SET
      email = $email,
      pass = crypto::argon2::generate($pass),
      created = time::now()
  )
  SIGNIN (
    SELECT * FROM user WHERE
      email = $email AND
      crypto::argon2::compare(pass, $pass)
  );

-- Row-level security
DEFINE TABLE post SCHEMAFUL
  PERMISSIONS
    FOR select FULL
    FOR create WHERE $auth.id != NONE
    FOR update WHERE author = $auth.id
    FOR delete WHERE author = $auth.id OR $auth.role = 'admin';
Enter fullscreen mode Exit fullscreen mode

HTTP API (No SDK Needed)

# Create a record
curl -X POST http://localhost:8000/sql \
  -H "Accept: application/json" \
  -H "NS: test" \
  -H "DB: test" \
  -u "root:root" \
  -d "CREATE user SET name = 'Alice', email = 'alice@example.com'"

# Query
curl -X POST http://localhost:8000/sql \
  -H "Accept: application/json" \
  -H "NS: test" \
  -H "DB: test" \
  -u "root:root" \
  -d "SELECT * FROM user"
Enter fullscreen mode Exit fullscreen mode

SurrealDB vs PostgreSQL vs MongoDB vs Neo4j

Feature SurrealDB PostgreSQL MongoDB Neo4j
Relational Yes Yes No No
Document Yes JSONB Yes No
Graph Yes No No (limited) Yes
Real-time Live queries LISTEN/NOTIFY Change streams No
Auth built-in Yes (scopes) Roles SCRAM Roles
Embedded Yes (WASM) No No No
Query language SurrealQL (SQL-like) SQL MQL Cypher

Need to scrape data from any website and get it in structured JSON? Check out my web scraping tools on Apify — no coding required, results in minutes.

Have a custom data extraction project? Email me at spinov001@gmail.com — I build tailored scraping solutions for businesses.

Top comments (0)