# Transactions

The Python SDK supports client-side transactions for executing multiple operations atomically over WebSocket connections.

The Python SDK supports client-side transactions that group multiple operations into a single atomic unit. All operations within a transaction either succeed together when committed or are rolled back entirely when cancelled. Transactions are scoped to a session and execute over a WebSocket connection.

This page covers how to create, execute, commit, cancel, and handle errors within transactions.

> [!NOTE]
> Transactions require a WebSocket connection (`ws://` or `wss://`) and must be created from a session. HTTP and embedded connections do not support transactions.

## API references

<table>
	<thead>
		<tr>
			<th scope="col">Method</th>
			<th scope="col">Description</th>
		</tr>
	</thead>
	<tbody>
		<tr>
			<td scope="row" data-label="Method"><a href="/docs/reference/python/api/core/surreal-session.md#begin-transaction"><code>session.begin_transaction()</code></a></td>
			<td scope="row" data-label="Description">Begins a new transaction within the session</td>
		</tr>
		<tr>
			<td scope="row" data-label="Method"><a href="/docs/reference/python/api/core/surreal-transaction.md#commit"><code>txn.commit()</code></a></td>
			<td scope="row" data-label="Description">Commits all operations in the transaction, making changes permanent</td>
		</tr>
		<tr>
			<td scope="row" data-label="Method"><a href="/docs/reference/python/api/core/surreal-transaction.md#cancel"><code>txn.cancel()</code></a></td>
			<td scope="row" data-label="Description">Cancels the transaction and rolls back all changes</td>
		</tr>
	</tbody>
</table>

## Creating a transaction

To create a transaction, first open a session with `.new_session()` on the connection, then call `.begin_transaction()` on the session. The returned transaction object provides the same data manipulation methods as the main connection, but all operations are held until the transaction is committed or cancelled.

**Synchronous**

		```python
		from surrealdb import Surreal

		with Surreal("ws://localhost:8000") as db:
		    db.use("surrealdb", "docs")
		    db.signin({"username": "root", "password": "secret"})

		    session = db.new_session()
		    session.use("surrealdb", "docs")

		    txn = session.begin_transaction()
		```

**Asynchronous**

		```python
		from surrealdb import AsyncSurreal

		async with AsyncSurreal("ws://localhost:8000") as db:
		    await db.use("surrealdb", "docs")
		    await db.signin({"username": "root", "password": "secret"})

		    session = await db.new_session()
		    await session.use("surrealdb", "docs")

		    txn = await session.begin_transaction()
		```

## Executing operations within a transaction

Once a transaction is created, use its methods - such as `.query()`, `.create()`, `.select()`, `.update()`, and `.delete()` - to perform operations. `.query()` returns a lazy builder, so remember to finish it with `.execute()` or `.first()`; nothing is sent to the server until you do. These operations are buffered within the transaction scope and are not visible to other connections or sessions until the transaction is committed.

**Synchronous**

		```python
		txn.create("users", {
		    "name": "Alice",
		    "email": "alice@example.com",
		    "age": 30,
		})

		txn.create("users", {
		    "name": "Bob",
		    "email": "bob@example.com",
		    "age": 25,
		})

		users = txn.query("SELECT * FROM users").first()
		```

**Asynchronous**

		```python
		await txn.create("users", {
		    "name": "Alice",
		    "email": "alice@example.com",
		    "age": 30,
		})

		await txn.create("users", {
		    "name": "Bob",
		    "email": "bob@example.com",
		    "age": 25,
		})

		users = await txn.query("SELECT * FROM users").first()
		```

Refer to the [SurrealTransaction API reference](/docs/reference/python/api/core/surreal-transaction.md) for the full list of methods available on the transaction object.

## Committing a transaction

Calling `.commit()` makes all operations in the transaction permanent. After committing, the changes become visible to other connections and sessions.

**Synchronous**

		```python
		txn.commit()
		```

**Asynchronous**

		```python
		await txn.commit()
		```

A transaction can only be committed once. After committing, the transaction object should not be reused.

## Cancelling a transaction

Calling `.cancel()` discards all operations in the transaction and rolls back any changes. The database state is restored to what it was before the transaction began.

**Synchronous**

		```python
		txn.cancel()
		```

**Asynchronous**

		```python
		await txn.cancel()
		```

## Handling errors in transactions

Use a `try`/`except` block to ensure that a transaction is cancelled if any operation fails. This prevents partial changes from being committed to the database.

**Synchronous**

		```python
		from surrealdb import Surreal

		with Surreal("ws://localhost:8000") as db:
		    db.use("surrealdb", "docs")
		    db.signin({"username": "root", "password": "secret"})

		    session = db.new_session()
		    session.use("surrealdb", "docs")

		    txn = session.begin_transaction()

		    try:
		        txn.create("users", {"name": "Alice", "age": 30})
		        txn.create("users", {"name": "Bob", "age": 25})
		        txn.commit()
		    except Exception:
		        txn.cancel()
		        raise
		```

**Asynchronous**

		```python
		from surrealdb import AsyncSurreal

		async with AsyncSurreal("ws://localhost:8000") as db:
		    await db.use("surrealdb", "docs")
		    await db.signin({"username": "root", "password": "secret"})

		    session = await db.new_session()
		    await session.use("surrealdb", "docs")

		    txn = await session.begin_transaction()

		    try:
		        await txn.create("users", {"name": "Alice", "age": 30})
		        await txn.create("users", {"name": "Bob", "age": 25})
		        await txn.commit()
		    except Exception:
		        await txn.cancel()
		        raise
		```

The `raise` at the end re-raises the original exception after cancelling the transaction, so the error is still visible to the caller.

## Learn more

- [SurrealTransaction API reference](/docs/reference/python/api/core/surreal-transaction.md) for transaction method signatures
- [SurrealSession API reference](/docs/reference/python/api/core/surreal-session.md) for session management
- [Multiple sessions](/docs/reference/python/concepts/multiple-sessions.md) for session setup
- [Error handling](/docs/reference/python/concepts/error-handling.md) for error recovery patterns
