# Transactions

Group operations into atomic transactions with the SurrealDB Kotlin SDK.

[Transactions](/docs/reference/query-language/language-primitives/transactions.md) group multiple operations so they either all succeed or all fail together. The Kotlin SDK exposes transactions as extension functions on a [session](/docs/reference/kotlin/concepts/multiple-sessions.md): a block form that commits or cancels automatically, and an explicit form for manual control.

> [!NOTE]
> Transactions require a stateful connection and are only available over the **WebSocket** transport. Check support with [`client.supports(SurrealFeature.Transactions)`](/docs/reference/kotlin/api/core/surreal-client.md#supports).

## 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/kotlin/api/core/transaction.md#transaction-block"><code>session.transaction { }</code></a></td>
			<td scope="row" data-label="Description">Runs a block, committing or cancelling automatically</td>
		</tr>
		<tr>
			<td scope="row" data-label="Method"><a href="/docs/reference/kotlin/api/core/transaction.md#begin-transaction"><code>session.beginTransaction()</code></a></td>
			<td scope="row" data-label="Description">Begins a transaction explicitly</td>
		</tr>
		<tr>
			<td scope="row" data-label="Method"><a href="/docs/reference/kotlin/api/core/transaction.md#commit"><code>tx.commit()</code></a></td>
			<td scope="row" data-label="Description">Commits the transaction</td>
		</tr>
		<tr>
			<td scope="row" data-label="Method"><a href="/docs/reference/kotlin/api/core/transaction.md#cancel"><code>tx.cancel()</code></a></td>
			<td scope="row" data-label="Description">Cancels the transaction</td>
		</tr>
	</tbody>
</table>

## Block form

The [`transaction { }`](/docs/reference/kotlin/api/core/transaction.md#transaction-block) builder runs your block against a [`SurrealTransaction`](/docs/reference/kotlin/api/core/transaction.md), commits it if the block returns normally, and cancels it if the block throws. The transaction is itself a queryable, so all the [CRUD builders](/docs/reference/kotlin/concepts/data-manipulation.md) are available scoped to it.

```kotlin
import com.surrealdb.kotlin.query.RecordId
import com.surrealdb.kotlin.transaction
import kotlinx.serialization.json.buildJsonObject
import kotlinx.serialization.json.put

client.transaction {
    create(RecordId("person", "tx"))
        .content(buildJsonObject { put("name", "Tx") })
        .await()

    update(RecordId("counter", "1"))
        .content(buildJsonObject { put("hits", 2) })
        .await()
}
```

## Explicit form

For finer control, begin a transaction with [`.beginTransaction()`](/docs/reference/kotlin/api/core/transaction.md#begin-transaction) and commit or cancel it yourself.

```kotlin
import com.surrealdb.kotlin.query.Table
import com.surrealdb.kotlin.beginTransaction
import kotlinx.serialization.json.buildJsonObject
import kotlinx.serialization.json.put

val tx = client.beginTransaction()
try {
    tx.create(Table("person"))
        .content(buildJsonObject { put("name", "Ada") })
        .await()
    tx.commit()
} catch (cause: Throwable) {
    tx.cancel()
    throw cause
}
```

## Learn more

- [Transaction reference](/docs/reference/kotlin/api/core/transaction.md) for the full API
- [Multiple sessions](/docs/reference/kotlin/concepts/multiple-sessions.md) - transactions run within a session
- [SurrealQL transactions](/docs/reference/query-language/language-primitives/transactions.md) for transaction semantics
