Multiple sessions
Sessions allow you to create isolated contexts on a single WebSocket connection. Each session has its own authentication state, namespace and database selection, and connection variables. This is useful when a single application needs to serve multiple users or tenants over one connection.
Sessions require a WebSocket connection (ws:// or wss://) and SurrealDB v3 or later.
API References
Creating a session
Call .Attach() on the *DB to create a new session. The session starts unauthenticated and without a selected namespace or database, so you must configure it before making queries.
session, err := db.Attach(ctx)
if err != nil {
log.Fatal(err)
}
defer session.Detach(ctx)
_, err = session.SignIn(ctx, surrealdb.Auth{
Username: "root",
Password: "root",
})
if err != nil {
log.Fatal(err)
}
if err := session.Use(ctx, "my_ns", "my_db"); err != nil {
log.Fatal(err)
}
Querying with a session
Sessions satisfy the sendable constraint, so all generic functions like Query, Select, Create, etc. accept a *Session directly.
results, err := surrealdb.Query[[]Person](ctx, session,
"SELECT * FROM persons",
nil,
)
Each session maintains its own state. Changes to variables, authentication, or namespace on one session do not affect the parent *DB or other sessions.
Session isolation
Sessions are fully isolated from each other and from the parent connection:
- Authentication is independent: signing in on a session does not affect other sessions or the
*DB. .Use() on a session does not change the namespace/database of other sessions.- Variables set with
.Let() are scoped to the session. - Live queries started on a session are scoped to that session.
sessionA, _ := db.Attach(ctx)
defer sessionA.Detach(ctx)
sessionB, _ := db.Attach(ctx)
defer sessionB.Detach(ctx)
sessionA.SignIn(ctx, surrealdb.Auth{Username: "admin", Password: "admin"})
sessionA.Use(ctx, "ns_a", "db_a")
sessionB.SignIn(ctx, surrealdb.Auth{Namespace: "ns_b", Database: "db_b", Access: "user_access", Username: "user1", Password: "pass1"})
sessionB.Use(ctx, "ns_b", "db_b")
Starting transactions from a session
Sessions can start their own transactions using .Begin(). The transaction inherits the session’s authentication and namespace context.
tx, err := session.Begin(ctx)
if err != nil {
log.Fatal(err)
}
defer tx.Cancel(ctx)
surrealdb.Create[any](ctx, tx, models.Table("events"), map[string]any{"type": "login"})
if err := tx.Commit(ctx); err != nil {
log.Fatal(err)
}
See Transactions for more on interactive transactions.
Detaching a session
Call .Detach() to remove the session from the server. After detaching, the session cannot be used and any operations on it return ErrSessionClosed.
if err := session.Detach(ctx); err != nil {
log.Fatal(err)
}
Use defer session.Detach(ctx) immediately after .Attach() to ensure cleanup.
Learn more