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.

MethodDescription
db.Attach(ctx)Creates a new session on the connection
session.Detach(ctx)Removes the session from the server
session.ID()Returns the session's UUID

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)
}

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.

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")

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.

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.

Was this page helpful?