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)
| Parameter | Type | Description |
|---|
url required | str | The 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)
| Parameter | Type | Description |
|---|
url required | str | The connection URL. The scheme determines the connection type. |
Returns: AsyncWsSurrealConnection | AsyncHttpSurrealConnection | AsyncEmbeddedSurrealConnection
URL Schemes
| Scheme | Connection Type | Description |
|---|
ws://, wss:// | WebSocket | Full-featured stateful connection. Supports live queries, sessions, and transactions. |
http://, https:// | HTTP | Stateless 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)
| Parameter | Type | Description |
|---|
url optional | str | None | An 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)
| Parameter | Type | Description |
|---|
namespace required | str | The namespace to use. |
database required | str | The 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)
Asynchronous
ver = await db.version()
print(ver)
Authentication Methods
.signup()
Signs up a user to a specific access method.
Method Syntax
db.signup(vars)
| Parameter | Type | Description |
|---|
vars required | 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)
| Parameter | Type | Description |
|---|
vars required | 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)
| Parameter | Type | Description |
|---|
token required | str | The 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)
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)
| Parameter | Type | Description |
|---|
key required | str | The name of the variable (without the $ prefix). |
value required | Value | The 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)
| Parameter | Type | Description |
|---|
key required | str | The 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)
When multiple statements are provided, .query() returns only the first statement’s result. If you need results from all statements, use .query_raw() instead.
| Parameter | Type | Description |
|---|
query required | str | The SurrealQL query string to execute. |
vars optional | dict[str, Value] | None | Variables 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)
| Parameter | Type | Description |
|---|
query required | str | The SurrealQL query string to execute. |
params optional | dict[str, Value] | None | Variables 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)
| Parameter | Type | Description |
|---|
record required | RecordIdType | A 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)
| Parameter | Type | Description |
|---|
record required | RecordIdType | The table name or RecordID to create. |
data optional | Value | None | The 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)
| Parameter | Type | Description |
|---|
record required | RecordIdType | The table name or RecordID to update. |
data optional | Value | None | The 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)
| Parameter | Type | Description |
|---|
record required | RecordIdType | The table name or RecordID to upsert. |
data optional | Value | None | The 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)
| Parameter | Type | Description |
|---|
record required | RecordIdType | The table name or RecordID to merge into. |
data optional | Value | None | The 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)
| Parameter | Type | Description |
|---|
record required | RecordIdType | The table name or RecordID to patch. |
data optional | Value | None | A 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)
| Parameter | Type | Description |
|---|
record required | RecordIdType | The 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)
| Parameter | Type | Description |
|---|
table required | str | Table | The table to insert into. |
data required | Value | A 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)
| Parameter | Type | Description |
|---|
table required | str | Table | The relation table to insert into. |
data required | Value | A 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 queries require a WebSocket connection (ws:// or wss://). HTTP and embedded connections raise UnsupportedFeatureError.
.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)
| Parameter | Type | Description |
|---|
table required | str | Table | The table to watch for changes. |
diff optional | bool | If 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)
| Parameter | Type | Description |
|---|
query_uuid required | str | UUID | The 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)
| Parameter | Type | Description |
|---|
query_uuid required | str | UUID | The UUID of the live query to kill. |
Returns: None
Examples
Synchronous
db.kill(query_uuid)
Asynchronous
await db.kill(query_uuid)
Sessions
Sessions require a WebSocket connection (ws:// or wss://). HTTP and embedded connections raise UnsupportedFeatureError.
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)
| Parameter | Type | Description |
|---|
session_id required | UUID | The session ID to detach from. |
Returns: None
Examples
Synchronous
db.detach(session_id)
Asynchronous
await db.detach(session_id)
Transactions
Transactions require a WebSocket connection (ws:// or wss://). HTTP and embedded connections raise UnsupportedFeatureError.
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)
| Parameter | Type | Description |
|---|
session_id optional | UUID | None | The 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)
| Parameter | Type | Description |
|---|
txn_id required | UUID | The transaction ID returned by .begin(). |
session_id optional | UUID | None | The 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)
| Parameter | Type | Description |
|---|
txn_id required | UUID | The transaction ID returned by .begin(). |
session_id optional | UUID | None | The 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