# Transactions

Run multiple statements atomically with the Mojo SDK over HTTP or a WebSocket session.

SurrealDB wraps every `query` RPC in its own implicit `BEGIN`/`COMMIT`, so a transaction has to live inside a single multi-statement query. The Mojo SDK gives you two ways to do this.

## Atomic multi-statement transactions

`transaction_multi` takes a list of statements, wraps them in `BEGIN TRANSACTION;` and `COMMIT TRANSACTION;`, and sends them as a single atomic query. This works on any transport and is the recommended approach over HTTP.

```python
var stmts = List[String]()
stmts.append("CREATE car:a SET wheels = 4;")
stmts.append("CREATE car:b SET wheels = 4;")
var resp = client.transaction_multi(stmts)
```

If any statement fails, the whole transaction is rolled back.

## Session transactions

Over a stateful WebSocket session, `begin_transaction()` returns a handle that buffers statements and flushes them on `commit()`. The handle exposes `query()`, `create()`, `select()`, `commit()`, and `cancel()`.

```python
from surrealdb import AsyncSurrealClient, CborCodec, ConnectOptions
from std.collections import Optional, List


def main():
    var client = AsyncSurrealClient()
    _ = client.connect(
        "ws://localhost:8000/rpc",
        ConnectOptions(
            namespace=Optional(String("test")),
            database=Optional(String("test")),
        ),
    )

    var codec = CborCodec()
    var pairs = List[Tuple[String, List[UInt8]]]()
    pairs.append(Tuple(String("user"), codec.encode_text("root")))
    pairs.append(Tuple(String("pass"), codec.encode_text("root")))
    _ = client.signin(codec.encode_map(pairs))
    client.use("test", "test")

    # BEGIN, do work, COMMIT.
    var txn = client.begin_transaction()
    _ = txn.query("CREATE person:alice SET age = 30;")
    _ = txn.query("CREATE person:bob   SET age = 31;")
    txn.commit()
```

Call `cancel()` instead of `commit()` to discard the buffered statements.

> [!NOTE]
> Session transactions run over a stateful WebSocket session. WebSocket support is rolling out; for atomic transactions over HTTP, use `transaction_multi`.

See the method reference for [`transaction_multi`](/docs/reference/mojo/methods/transaction-multi.md) and [`begin_transaction`](/docs/reference/mojo/methods/begin-transaction.md).
