---
title: "Transactions"
description: "Perform multi-record transactions (MRT) with the Aerospike Rust client using aerospike::txn."
---

# Transactions

> For the complete documentation index see: [llms.txt](https://aerospike.com/docs/llms.txt)
> 
> All documentation pages available in markdown.

## Applies to

Multi-record transactions require Rust client **3.0.0**, Aerospike Database **Enterprise Edition 8.0** or later, and a [strong-consistency namespace](https://aerospike.com/docs/database/manage/namespace/consistency).

`Txn::new()` uses a default timeout of `0`, which defers to the server’s transaction-duration limit (10 seconds by default). Set an explicit timeout on `Txn` when you need a different bound.

See [Create and use transactions](https://aerospike.com/docs/database/learn/transactions/) for database concepts and error handling patterns.

## Commit a transaction

Create a `Txn`, attach it to each write policy used inside the transaction, perform writes, then call `Client::commit()`.

```rust
use std::sync::Arc;

use aerospike::{as_bin, as_key, Bins, Client, ReadPolicy, Txn, WritePolicy};

let txn = Arc::new(Txn::new());

println!("begin transaction {}", txn.id());

let mut wp = WritePolicy::default();

wp.base_policy.txn = Some(txn.clone());

let key1 = as_key!("test", "txn_demo", "account-a");

let key2 = as_key!("test", "txn_demo", "account-b");

client.put(&wp, &key1, &[as_bin!("balance", 70)]).await?;

client.put(&wp, &key2, &[as_bin!("balance", 30)]).await?;

let status = client.commit(&txn).await?;

println!("commit status: {status:?}");

let rpolicy = ReadPolicy::default();

let a = client.get(&rpolicy, &key1, Bins::All).await?;

let b = client.get(&rpolicy, &key2, Bins::All).await?;

println!("after commit: A = {:?}, B = {:?}", a.bins.get("balance"), b.bins.get("balance"));
```

> 📖 **API reference**: [`Txn`](https://docs.rs/aerospike/latest/aerospike/struct.Txn.html) | [`Client::commit`](https://docs.rs/aerospike/latest/aerospike/struct.Client.html#method.commit)

## Abort a transaction

Calling `abort()` when validation fails is an application-level choice made **before** `commit()`. Use it to roll back writes when you decide not to commit.

Do **not** call `abort()` as the response to a failed `commit()`. If `commit()` returns an error and the transaction is [in doubt](https://aerospike.com/docs/database/learn/transactions), call `commit()` again until the outcome is known. The server may still be able to complete the transaction.

```rust
let txn = Arc::new(Txn::new());

let mut wp = WritePolicy::default();

wp.base_policy.txn = Some(txn.clone());

client.put(&wp, &key1, &[as_bin!("balance", -1000)]).await?;

let status = client.abort(&txn).await?;

println!("abort status: {status:?}");
```

> 📖 **API reference**: [`Client::abort`](https://docs.rs/aerospike/latest/aerospike/struct.Client.html#method.abort)

## Error handling

Commit failures surface as `ErrorKind::Commit` on the opaque `Error` type. See [Error handling](https://aerospike.com/docs/develop/client/rust/error-handling) for accessors.

When `commit()` fails, check whether the transaction is still in doubt. If it is, call `commit()` again rather than `abort()` until the server reports a final outcome. Use `abort()` only when your application decides not to commit before the first `commit()` attempt.