Surreal / AsyncSurreal

The Surreal and AsyncSurreal factory functions create a connection to a SurrealDB instance. They inspect the URL scheme and return the appropriate connection class — WebSocket, HTTP, or embedded — so you use the same interface regardless of protocol.

Surreal(url) returns a blocking (synchronous) connection. AsyncSurreal(url) returns an asynchronous connection. Both expose the same set of methods; the async variants must be awaited.

Source: surrealdb.py

Factory Functions

Surreal(url)

Creates a synchronous connection based on the URL scheme.

Syntax

from surrealdb import Surreal

db = Surreal(url)
ParameterTypeDescription
url strThe connection URL. The scheme determines the connection type.

Returns: BlockingWsSurrealConnection | BlockingHttpSurrealConnection | BlockingEmbeddedSurrealConnection

AsyncSurreal(url)

Creates an asynchronous connection based on the URL scheme.

Syntax

from surrealdb import AsyncSurreal

db = AsyncSurreal(url)
ParameterTypeDescription
url strThe connection URL. The scheme determines the connection type.

Returns: AsyncWsSurrealConnection | AsyncHttpSurrealConnection | AsyncEmbeddedSurrealConnection

URL Schemes

SchemeConnection TypeDescription
ws://, wss://WebSocketFull-featured stateful connection. Supports live queries, sessions, and transactions.
http://, https://HTTPStateless connection. Each request is independent.
mem://, memory://Embedded (in-memory)In-process database that does not persist data.
file://, surrealkv://Embedded (on-disk)In-process database backed by SurrealKV storage.

Examples

WebSocket

from surrealdb import Surreal

db = Surreal("ws://localhost:8000")

HTTP

from surrealdb import Surreal

db = Surreal("https://cloud.surrealdb.com")

Embedded in-memory

from surrealdb import Surreal

db = Surreal("mem://")

Embedded on-disk

from surrealdb import Surreal

db = Surreal("surrealkv://path/to/database")

Async WebSocket

from surrealdb import AsyncSurreal

db = AsyncSurreal("ws://localhost:8000")

Connection Methods

.connect()

Opens the connection to the SurrealDB instance. The URL can optionally be overridden here.

Method Syntax

db.connect(url)
ParameterTypeDescription
url str | NoneAn optional URL to override the one provided to the factory function. Defaults to None.

Returns: None

Examples

Synchronous

from surrealdb import Surreal

db = Surreal("ws://localhost:8000")
db.connect()

Asynchronous

from surrealdb import AsyncSurreal

db = AsyncSurreal("ws://localhost:8000")
await db.connect()

Override URL

db = Surreal("ws://localhost:8000")
db.connect("ws://other-host:8000")

.close()

Closes the active connection and releases resources.

Method Syntax

db.close()

Returns: None

Examples

Synchronous

db.close()

Asynchronous

await db.close()

.use()

Switches to a specific namespace and database.

Method Syntax

db.use(namespace, database)
ParameterTypeDescription
namespace strThe namespace to use.
database strThe database to use.

Returns: None

Examples

Synchronous

db.use("my_namespace", "my_database")

Asynchronous

await db.use("my_namespace", "my_database")

.version()

Returns the version string of the connected SurrealDB instance.

Method Syntax

db.version()

Returns: str

Examples

Synchronous

ver = db.version()
print(ver) # e.g. "surrealdb-2.2.0"

Asynchronous

ver = await db.version()
print(ver)

Authentication Methods

.signup()

Signs up a user to a specific access method.

Method Syntax

db.signup(vars)
ParameterTypeDescription
vars dict[str, Value]Variables used for signup, including namespace, database, access, and any additional fields required by the access method.

Returns: Tokens

Examples

Synchronous

token = db.signup({
"namespace": "my_namespace",
"database": "my_database",
"access": "user_access",
"email": "user@example.com",
"password": "s3cret",
})

Asynchronous

token = await db.signup({
"namespace": "my_namespace",
"database": "my_database",
"access": "user_access",
"email": "user@example.com",
"password": "s3cret",
})

.signin()

Signs in to the database with the given credentials.

Method Syntax

db.signin(vars)
ParameterTypeDescription
vars dict[str, Value]Credentials for authentication. For root access, provide username and password. For scoped access, also include namespace, database, and access.

Returns: Tokens

Examples

Root signin (sync)

token = db.signin({
"username": "root",
"password": "root",
})

Root signin (async)

token = await db.signin({
"username": "root",
"password": "root",
})

Scoped signin

token = db.signin({
"namespace": "my_namespace",
"database": "my_database",
"access": "user_access",
"email": "user@example.com",
"password": "s3cret",
})

.authenticate()

Authenticates the current connection with a JWT token.

Method Syntax

db.authenticate(token)
ParameterTypeDescription
token strThe JWT token to authenticate with.

Returns: None

Examples

Synchronous

db.authenticate("eyJhbGciOiJIUzI1NiIs...")

Asynchronous

await db.authenticate("eyJhbGciOiJIUzI1NiIs...")

.invalidate()

Invalidates the authentication for the current connection, removing the associated JWT token.

Method Syntax

db.invalidate()

Returns: None

Examples

Synchronous

db.invalidate()

Asynchronous

await db.invalidate()

.info()

Returns the record of the currently authenticated user.

Method Syntax

db.info()

Returns: Value

Examples

Synchronous

user = db.info()
print(user) # e.g. {"id": "users:john", "email": "john@example.com"}

Asynchronous

user = await db.info()

Variables

.let()

Defines a variable on the current connection that can be used in subsequent queries.

Method Syntax

db.let(key, value)
ParameterTypeDescription
key strThe name of the variable (without the $ prefix).
value ValueThe value to assign to the variable.

Returns: None

Examples

Synchronous

db.let("user_id", RecordID("users", "john"))
result = db.query("SELECT * FROM users WHERE id = $user_id")

Asynchronous

await db.let("user_id", RecordID("users", "john"))
result = await db.query("SELECT * FROM users WHERE id = $user_id")

.unset()

Removes a previously defined variable from the current connection.

Method Syntax

db.unset(key)
ParameterTypeDescription
key strThe name of the variable to remove.

Returns: None

Examples

Synchronous

db.unset("user_id")

Asynchronous

await db.unset("user_id")

Query Methods

.query()

Runs a set of SurrealQL statements against the database.

Method Syntax

db.query(query, vars)
ParameterTypeDescription
query strThe SurrealQL query string to execute.
vars dict[str, Value] | NoneVariables to bind into the query. Defaults to None.

Returns: Value

Examples

Synchronous

result = db.query(
"SELECT * FROM users WHERE age > $min_age",
{"min_age": 18},
)

Asynchronous

result = await db.query(
"SELECT * FROM users WHERE age > $min_age",
{"min_age": 18},
)

Without variables

result = db.query("SELECT * FROM users")

.query_raw()

Runs a set of SurrealQL statements and returns the raw RPC response, including per-statement results, statuses, and execution times. Unlike .query(), errors in individual statements are returned in the response rather than raised as exceptions.

Method Syntax

db.query_raw(query, params)
ParameterTypeDescription
query strThe SurrealQL query string to execute.
params dict[str, Value] | NoneVariables to bind into the query. Defaults to None.

Returns: dict[str, Any]

Examples

Synchronous

raw = db.query_raw(
"CREATE users SET name = $name; SELECT * FROM users;",
{"name": "John"},
)

for statement in raw["result"]:
print(statement["status"], statement["time"])

Asynchronous

raw = await db.query_raw(
"CREATE users SET name = $name; SELECT * FROM users;",
{"name": "John"},
)

CRUD Methods

.select()

Selects all records in a table, or a specific record by its ID.

Method Syntax

db.select(record)
ParameterTypeDescription
record RecordIdTypeA table name (str) or a RecordID to select.

Returns: Value

Examples

Synchronous

users = db.select("users")

user = db.select(RecordID("users", "john"))

Asynchronous

users = await db.select("users")

user = await db.select(RecordID("users", "john"))

.create()

Creates a record in a table. If a RecordID is passed, the record is created with that specific ID. If a table name is passed, a random ID is generated.

Method Syntax

db.create(record, data)
ParameterTypeDescription
record RecordIdTypeThe table name or RecordID to create.
data Value | NoneThe record data. Defaults to None.

Returns: Value

Examples

Synchronous

user = db.create("users", {
"name": "John",
"email": "john@example.com",
})

product = db.create(RecordID("products", "apple"), {
"name": "Apple",
"price": 1.50,
})

Asynchronous

user = await db.create("users", {
"name": "John",
"email": "john@example.com",
})

.update()

Replaces the entire record with the given data. Fields not present in data are removed.

Method Syntax

db.update(record, data)
ParameterTypeDescription
record RecordIdTypeThe table name or RecordID to update.
data Value | NoneThe new record data. Defaults to None.

Returns: Value

Examples

Synchronous

db.update(RecordID("users", "john"), {
"name": "John Doe",
"email": "john.doe@example.com",
})

Asynchronous

await db.update(RecordID("users", "john"), {
"name": "John Doe",
"email": "john.doe@example.com",
})

.upsert()

Updates an existing record or creates a new one if it does not exist. Replaces the entire record content.

Method Syntax

db.upsert(record, data)
ParameterTypeDescription
record RecordIdTypeThe table name or RecordID to upsert.
data Value | NoneThe record data. Defaults to None.

Returns: Value

Examples

Synchronous

db.upsert(RecordID("users", "john"), {
"name": "John",
"email": "john@example.com",
})

Asynchronous

await db.upsert(RecordID("users", "john"), {
"name": "John",
"email": "john@example.com",
})

.merge()

Merges the given data into an existing record. Existing fields not present in data are preserved.

Method Syntax

db.merge(record, data)
ParameterTypeDescription
record RecordIdTypeThe table name or RecordID to merge into.
data Value | NoneThe data to merge. Defaults to None.

Returns: Value

Examples

Synchronous

db.merge(RecordID("users", "john"), {
"age": 32,
})

Asynchronous

await db.merge(RecordID("users", "john"), {
"age": 32,
})

.patch()

Applies JSON Patch operations to a record.

Method Syntax

db.patch(record, data)
ParameterTypeDescription
record RecordIdTypeThe table name or RecordID to patch.
data Value | NoneA list of JSON Patch operations. Defaults to None.

Returns: Value

Examples

Synchronous

db.patch(RecordID("users", "john"), [
{"op": "replace", "path": "/email", "value": "new@example.com"},
{"op": "add", "path": "/verified", "value": True},
])

Asynchronous

await db.patch(RecordID("users", "john"), [
{"op": "replace", "path": "/email", "value": "new@example.com"},
])

.delete()

Deletes all records in a table, or a specific record by its ID.

Method Syntax

db.delete(record)
ParameterTypeDescription
record RecordIdTypeThe table name or RecordID to delete.

Returns: Value

Examples

Synchronous

db.delete(RecordID("users", "john"))

db.delete("temp_data")

Asynchronous

await db.delete(RecordID("users", "john"))

Insert Methods

.insert()

Inserts one or more records into a table.

Method Syntax

db.insert(table, data)
ParameterTypeDescription
table str | TableThe table to insert into.
data ValueA single record dict or a list of record dicts to insert.

Returns: Value

Examples

Synchronous

db.insert("users", {"name": "Alice", "email": "alice@example.com"})

db.insert("users", [
{"name": "Bob", "email": "bob@example.com"},
{"name": "Charlie", "email": "charlie@example.com"},
])

Asynchronous

await db.insert("users", {"name": "Alice", "email": "alice@example.com"})

.insert_relation()

Inserts one or more relation records into a relation table.

Method Syntax

db.insert_relation(table, data)
ParameterTypeDescription
table str | TableThe relation table to insert into.
data ValueA single relation dict or a list of relation dicts. Each must include in and out fields.

Returns: Value

Examples

Synchronous

db.insert_relation("likes", {
"in": RecordID("users", "alice"),
"out": RecordID("posts", "post1"),
"created_at": "2025-01-01T00:00:00Z",
})

Asynchronous

await db.insert_relation("likes", {
"in": RecordID("users", "alice"),
"out": RecordID("posts", "post1"),
})

Live Queries

.live()

Initiates a live query for a table. Returns a UUID that identifies the live query and can be passed to .subscribe_live() and .kill().

Method Syntax

db.live(table, diff)
ParameterTypeDescription
table str | TableThe table to watch for changes.
diff boolIf True, notifications include JSON Patch diffs instead of full records. Defaults to False.

Returns: UUID

Examples

Synchronous

query_uuid = db.live("users")

query_uuid = db.live("users", diff=True)

Asynchronous

query_uuid = await db.live("users")

.subscribe_live()

Returns a generator that yields live query notifications for the given query UUID. Each notification is a dict containing the action ("CREATE", "UPDATE", "DELETE"), the record data, and the record ID.

Method Syntax

db.subscribe_live(query_uuid)
ParameterTypeDescription
query_uuid str | UUIDThe UUID of the live query returned by .live().

Returns (sync): Generator[dict[str, Value], None, None] Returns (async): AsyncGenerator[dict[str, Value], None]

Examples

Synchronous

query_uuid = db.live("users")

for notification in db.subscribe_live(query_uuid):
print(notification["action"], notification["result"])

Asynchronous

query_uuid = await db.live("users")

async for notification in db.subscribe_live(query_uuid):
print(notification["action"], notification["result"])

.kill()

Terminates a running live query by its UUID.

Method Syntax

db.kill(query_uuid)
ParameterTypeDescription
query_uuid str | UUIDThe UUID of the live query to kill.

Returns: None

Examples

Synchronous

db.kill(query_uuid)

Asynchronous

await db.kill(query_uuid)

Sessions

Sessions allow you to create isolated contexts on a single connection, each with its own namespace, database, variables, and authentication state.

.new_session()

Creates a new isolated session on the current connection.

Method Syntax

db.new_session()

Returns (sync): BlockingSurrealSession Returns (async): AsyncSurrealSession

Examples

Synchronous

session = db.new_session()
session.use("other_ns", "other_db")
result = session.select("users")

Asynchronous

session = await db.new_session()
await session.use("other_ns", "other_db")
result = await session.select("users")

.attach()

Attaches to the server-side session associated with this connection and returns its session ID.

Method Syntax

db.attach()

Returns: UUID

Examples

Synchronous

session_id = db.attach()

Asynchronous

session_id = await db.attach()

.detach()

Detaches from a server-side session.

Method Syntax

db.detach(session_id)
ParameterTypeDescription
session_id UUIDThe session ID to detach from.

Returns: None

Examples

Synchronous

db.detach(session_id)

Asynchronous

await db.detach(session_id)

Transactions

Transactions let you group multiple operations into an atomic unit. Changes are only applied when the transaction is committed, and can be rolled back with cancel.

.begin()

Begins a new transaction, optionally within a specific session.

Method Syntax

db.begin(session_id)
ParameterTypeDescription
session_id UUID | NoneThe session to start the transaction in. If None, uses the default session. Defaults to None.

Returns: UUID — the transaction ID

Examples

Synchronous

txn_id = db.begin()

Asynchronous

txn_id = await db.begin()

Within a session

session_id = db.attach()
txn_id = db.begin(session_id)

.commit()

Commits a transaction, applying all changes made within it.

Method Syntax

db.commit(txn_id, session_id)
ParameterTypeDescription
txn_id UUIDThe transaction ID returned by .begin().
session_id UUID | NoneThe session the transaction belongs to. Defaults to None.

Returns: None

Examples

Synchronous

txn_id = db.begin()
db.query("CREATE users SET name = 'Alice'")
db.commit(txn_id)

Asynchronous

txn_id = await db.begin()
await db.query("CREATE users SET name = 'Alice'")
await db.commit(txn_id)

.cancel()

Cancels a transaction, discarding all changes made within it.

Method Syntax

db.cancel(txn_id, session_id)
ParameterTypeDescription
txn_id UUIDThe transaction ID returned by .begin().
session_id UUID | NoneThe session the transaction belongs to. Defaults to None.

Returns: None

Examples

Synchronous

txn_id = db.begin()
db.query("DELETE users")
db.cancel(txn_id)

Asynchronous

txn_id = await db.begin()
await db.query("DELETE users")
await db.cancel(txn_id)

Context Manager

Both Surreal and AsyncSurreal support the context manager protocol. The connection is automatically opened on entry and closed on exit.

Synchronous

Synchronous context manager

from surrealdb import Surreal

with Surreal("ws://localhost:8000") as db:
db.use("my_namespace", "my_database")
db.signin({"username": "root", "password": "root"})
users = db.select("users")

Asynchronous

Asynchronous context manager

from surrealdb import AsyncSurreal

async with AsyncSurreal("ws://localhost:8000") as db:
await db.use("my_namespace", "my_database")
await db.signin({"username": "root", "password": "root"})
users = await db.select("users")

Complete Example

Full workflow (sync)

from surrealdb import Surreal, RecordID

with Surreal("ws://localhost:8000") as db:
db.use("shop", "inventory")
db.signin({"username": "root", "password": "root"})

db.create("products", {"name": "Laptop", "price": 999.99})
db.create("products", {"name": "Mouse", "price": 29.99})

products = db.select("products")
print("All products:", products)

cheap = db.query(
"SELECT * FROM products WHERE price < $max",
{"max": 100},
)
print("Affordable:", cheap)

db.merge(RecordID("products", products[0]["id"].id), {"stock": 50})

db.delete(RecordID("products", products[1]["id"].id))

Full workflow (async)

import asyncio
from surrealdb import AsyncSurreal, RecordID

async def main():
async with AsyncSurreal("ws://localhost:8000") as db:
await db.use("shop", "inventory")
await db.signin({"username": "root", "password": "root"})

await db.create("products", {"name": "Laptop", "price": 999.99})

products = await db.select("products")
print("Products:", products)

asyncio.run(main())

See Also