• Start

Authentication

/

Better Auth

Transactions & limitations

How the @surrealdb/better-auth adapter handles transactions, and the current limitations to be aware of.

Transaction support is built in. Better Auth uses transactions internally for operations that need atomicity (for example, creating a session alongside a new user record), so most applications never call the transaction API directly.

If you need manual transaction access, call transaction on the adapter. Operations run inside the callback are committed together when it resolves, or discarded if it throws.

const adapter = surrealAdapter({ db })(options);

await adapter.transaction(async (trx) => {
await trx.create({ model: 'user', data: { /* ... */ } });
await trx.create({ model: 'session', data: { /* ... */ } });
});

Transactions are backed by SurrealDB.beginTransaction(). If any operation inside the callback throws, the transaction is cancelled and changes are discarded.

Keep the following in mind when adopting the adapter.

The adapter targets Better Auth 1.6.x and SurrealDB 3.1+. Other major versions of either dependency are not supported.

By default Better Auth uses string identifiers, and UUIDs can be enabled in your Better Auth configuration. Numeric (auto-increment) identifier strategies are not supported, because SurrealDB does not generate them natively and the adapter has no JavaScript fallback for them.

With the default schemaMode: 'schemafull', writes to fields that are not in the generated schema are rejected. Whenever you add a plugin or otherwise introduce new fields, regenerate and reapply the schema. If you would rather not regenerate each time, set schemaMode: 'schemaless'; known fields stay typed and indexed, and writes to undeclared fields are accepted.

SurrealDB's cancel() is not honoured in every setup (for example, the in-memory engine). To keep rollback reliable, the adapter compensates by deleting records it created inside a failed transaction. This covers records created during the transaction; it does not restore prior values for rows that were updated or deleted within it.

When reading records, the adapter converts SurrealDB types back to JavaScript values: a datetime becomes a JavaScript Date, and a RecordId becomes its string id. Bear this in mind if you query the underlying tables directly rather than through Better Auth.

Was this page helpful?