# Transactions & limitations

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

## Transactions

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.

```typescript
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()`](/docs/reference/query-language/statements/begin.md). If any operation inside the callback throws, the transaction is cancelled and changes are discarded.

## Limitations

Keep the following in mind when adopting the adapter.

### Version coupling

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

### Numeric identifiers are not supported

By default Better Auth uses string identifiers, and [UUIDs](/docs/build/integrations/authentication/better-auth/overview.md#identifiers) 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.

### `SCHEMAFULL` schemas require regeneration

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](/docs/build/integrations/authentication/better-auth/getting-started.md#schema-generation). If you would rather not regenerate each time, set `schemaMode: 'schemaless'`; known fields stay typed and indexed, and writes to undeclared fields are accepted.

### Transaction rollback is best-effort

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.

### Value deserialisation

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.
