or run

npx @tessl/cli init
Log in

Version

Tile

Overview

Evals

Files

Files

docs

backup-restore.mddata-operations.mdglobal-tables.mdimport-export.mdindex.mdpartiql.mdtable-management.mdtransactions.md

transactions.mddocs/

0

# Transactions

1

2

ACID transaction support for complex multi-item operations with strong consistency guarantees. DynamoDB transactions allow you to perform multiple operations across multiple items and tables atomically, ensuring data consistency and integrity.

3

4

## Capabilities

5

6

### Transact Write Items

7

8

Performs a synchronous write operation that groups up to 100 action requests as a single atomic transaction.

9

10

```java { .api }

11

/**

12

* Synchronous write operation that groups up to 100 action requests

13

* @param request - The request containing transaction items and options

14

* @return Response containing consumed capacity and item collection metrics

15

*/

16

TransactWriteItemsResponse transactWriteItems(TransactWriteItemsRequest request);

17

18

class TransactWriteItemsRequest {

19

static Builder builder();

20

21

/** An ordered array of up to 100 TransactWriteItem objects */

22

List<TransactWriteItem> transactItems();

23

Builder transactItems(Collection<TransactWriteItem> transactItems);

24

25

/** Determines the level of detail about consumed capacity returned */

26

ReturnConsumedCapacity returnConsumedCapacity();

27

Builder returnConsumedCapacity(ReturnConsumedCapacity returnConsumedCapacity);

28

29

/** Determines whether item collection metrics are returned */

30

ReturnItemCollectionMetrics returnItemCollectionMetrics();

31

Builder returnItemCollectionMetrics(ReturnItemCollectionMetrics returnItemCollectionMetrics);

32

33

/** Providing a ClientRequestToken makes the call idempotent */

34

String clientRequestToken();

35

Builder clientRequestToken(String clientRequestToken);

36

}

37

38

class TransactWriteItem {

39

static Builder builder();

40

41

/** A request to perform a check item operation */

42

ConditionCheck conditionCheck();

43

Builder conditionCheck(ConditionCheck conditionCheck);

44

45

/** A request to perform a PutItem operation */

46

Put put();

47

Builder put(Put put);

48

49

/** A request to perform a DeleteItem operation */

50

Delete delete();

51

Builder delete(Delete delete);

52

53

/** A request to perform an UpdateItem operation */

54

Update update();

55

Builder update(Update update);

56

}

57

58

class ConditionCheck {

59

static Builder builder();

60

61

/** Name of the table for the check item request */

62

String tableName();

63

Builder tableName(String tableName);

64

65

/** The primary key of the item to be checked */

66

Map<String, AttributeValue> key();

67

Builder key(Map<String, AttributeValue> key);

68

69

/** A condition that must be satisfied to include an item in the response */

70

String conditionExpression();

71

Builder conditionExpression(String conditionExpression);

72

73

/** One or more substitution tokens for attribute names in expressions */

74

Map<String, String> expressionAttributeNames();

75

Builder expressionAttributeNames(Map<String, String> expressionAttributeNames);

76

77

/** One or more values that can be substituted in expressions */

78

Map<String, AttributeValue> expressionAttributeValues();

79

Builder expressionAttributeValues(Map<String, AttributeValue> expressionAttributeValues);

80

81

/** Use ReturnValuesOnConditionCheckFailure to get the item attributes if the condition fails */

82

ReturnValuesOnConditionCheckFailure returnValuesOnConditionCheckFailure();

83

Builder returnValuesOnConditionCheckFailure(ReturnValuesOnConditionCheckFailure returnValuesOnConditionCheckFailure);

84

}

85

86

class Put {

87

static Builder builder();

88

89

/** A map of attribute name/value pairs, one for each attribute */

90

Map<String, AttributeValue> item();

91

Builder item(Map<String, AttributeValue> item);

92

93

/** Name of the table for the put item request */

94

String tableName();

95

Builder tableName(String tableName);

96

97

/** A condition that must be satisfied to include an item in the response */

98

String conditionExpression();

99

Builder conditionExpression(String conditionExpression);

100

101

/** One or more substitution tokens for attribute names in expressions */

102

Map<String, String> expressionAttributeNames();

103

Builder expressionAttributeNames(Map<String, String> expressionAttributeNames);

104

105

/** One or more values that can be substituted in expressions */

106

Map<String, AttributeValue> expressionAttributeValues();

107

Builder expressionAttributeValues(Map<String, AttributeValue> expressionAttributeValues);

108

109

/** Use ReturnValuesOnConditionCheckFailure to get the item attributes if the condition fails */

110

ReturnValuesOnConditionCheckFailure returnValuesOnConditionCheckFailure();

111

Builder returnValuesOnConditionCheckFailure(ReturnValuesOnConditionCheckFailure returnValuesOnConditionCheckFailure);

112

}

113

114

class Delete {

115

static Builder builder();

116

117

/** The primary key of the item to be deleted */

118

Map<String, AttributeValue> key();

119

Builder key(Map<String, AttributeValue> key);

120

121

/** Name of the table for the delete item request */

122

String tableName();

123

Builder tableName(String tableName);

124

125

/** A condition that must be satisfied to include an item in the response */

126

String conditionExpression();

127

Builder conditionExpression(String conditionExpression);

128

129

/** One or more substitution tokens for attribute names in expressions */

130

Map<String, String> expressionAttributeNames();

131

Builder expressionAttributeNames(Map<String, String> expressionAttributeNames);

132

133

/** One or more values that can be substituted in expressions */

134

Map<String, AttributeValue> expressionAttributeValues();

135

Builder expressionAttributeValues(Map<String, AttributeValue> expressionAttributeValues);

136

137

/** Use ReturnValuesOnConditionCheckFailure to get the item attributes if the condition fails */

138

ReturnValuesOnConditionCheckFailure returnValuesOnConditionCheckFailure();

139

Builder returnValuesOnConditionCheckFailure(ReturnValuesOnConditionCheckFailure returnValuesOnConditionCheckFailure);

140

}

141

142

class Update {

143

static Builder builder();

144

145

/** The primary key of the item to be updated */

146

Map<String, AttributeValue> key();

147

Builder key(Map<String, AttributeValue> key);

148

149

/** Name of the table for the update item request */

150

String tableName();

151

Builder tableName(String tableName);

152

153

/** An expression that defines one or more attributes to be updated */

154

String updateExpression();

155

Builder updateExpression(String updateExpression);

156

157

/** A condition that must be satisfied to include an item in the response */

158

String conditionExpression();

159

Builder conditionExpression(String conditionExpression);

160

161

/** One or more substitution tokens for attribute names in expressions */

162

Map<String, String> expressionAttributeNames();

163

Builder expressionAttributeNames(Map<String, String> expressionAttributeNames);

164

165

/** One or more values that can be substituted in expressions */

166

Map<String, AttributeValue> expressionAttributeValues();

167

Builder expressionAttributeValues(Map<String, AttributeValue> expressionAttributeValues);

168

169

/** Use ReturnValuesOnConditionCheckFailure to get the item attributes if the condition fails */

170

ReturnValuesOnConditionCheckFailure returnValuesOnConditionCheckFailure();

171

Builder returnValuesOnConditionCheckFailure(ReturnValuesOnConditionCheckFailure returnValuesOnConditionCheckFailure);

172

}

173

174

class TransactWriteItemsResponse {

175

/** The capacity units consumed by the entire transaction */

176

List<ConsumedCapacity> consumedCapacity();

177

178

/** A list of tables that were processed by TransactWriteItems and their item collection metrics */

179

Map<String, List<ItemCollectionMetrics>> itemCollectionMetrics();

180

}

181

```

182

183

**Usage Example:**

184

185

```java

186

import software.amazon.awssdk.services.dynamodb.DynamoDbClient;

187

import software.amazon.awssdk.services.dynamodb.model.*;

188

import java.util.List;

189

import java.util.Map;

190

191

DynamoDbClient client = DynamoDbClient.builder().build();

192

193

// Transfer money between accounts atomically

194

List<TransactWriteItem> transactItems = List.of(

195

// Debit from source account

196

TransactWriteItem.builder()

197

.update(Update.builder()

198

.tableName("Accounts")

199

.key(Map.of("accountId", AttributeValue.builder().s("account1").build()))

200

.updateExpression("SET balance = balance - :amount")

201

.conditionExpression("balance >= :amount") // Ensure sufficient funds

202

.expressionAttributeValues(Map.of(

203

":amount", AttributeValue.builder().n("100.00").build()

204

))

205

.build())

206

.build(),

207

208

// Credit to destination account

209

TransactWriteItem.builder()

210

.update(Update.builder()

211

.tableName("Accounts")

212

.key(Map.of("accountId", AttributeValue.builder().s("account2").build()))

213

.updateExpression("SET balance = balance + :amount")

214

.conditionExpression("attribute_exists(accountId)") // Ensure account exists

215

.expressionAttributeValues(Map.of(

216

":amount", AttributeValue.builder().n("100.00").build()

217

))

218

.build())

219

.build(),

220

221

// Log the transaction

222

TransactWriteItem.builder()

223

.put(Put.builder()

224

.tableName("TransactionLogs")

225

.item(Map.of(

226

"transactionId", AttributeValue.builder().s("txn-123").build(),

227

"fromAccount", AttributeValue.builder().s("account1").build(),

228

"toAccount", AttributeValue.builder().s("account2").build(),

229

"amount", AttributeValue.builder().n("100.00").build(),

230

"timestamp", AttributeValue.builder().s("2025-09-07T17:30:00Z").build()

231

))

232

.conditionExpression("attribute_not_exists(transactionId)") // Prevent duplicates

233

.build())

234

.build()

235

);

236

237

try {

238

TransactWriteItemsResponse response = client.transactWriteItems(

239

TransactWriteItemsRequest.builder()

240

.transactItems(transactItems)

241

.returnConsumedCapacity(ReturnConsumedCapacity.TOTAL)

242

.clientRequestToken("transfer-123") // For idempotency

243

.build()

244

);

245

246

System.out.println("Transaction completed successfully");

247

System.out.println("Total consumed capacity: " +

248

response.consumedCapacity().stream()

249

.mapToDouble(cc -> cc.capacityUnits())

250

.sum());

251

252

} catch (TransactionCanceledException e) {

253

System.err.println("Transaction failed: " + e.getMessage());

254

// Handle transaction failure (e.g., insufficient funds, account doesn't exist)

255

}

256

```

257

258

### Transact Get Items

259

260

Retrieves multiple items from one or more tables in a single atomic operation.

261

262

```java { .api }

263

/**

264

* Synchronous read operation that groups up to 100 Get actions together

265

* @param request - The request containing transaction items and options

266

* @return Response containing retrieved items and consumed capacity

267

*/

268

TransactGetItemsResponse transactGetItems(TransactGetItemsRequest request);

269

270

class TransactGetItemsRequest {

271

static Builder builder();

272

273

/** An ordered array of up to 100 TransactGetItem objects */

274

List<TransactGetItem> transactItems();

275

Builder transactItems(Collection<TransactGetItem> transactItems);

276

277

/** Determines the level of detail about consumed capacity returned */

278

ReturnConsumedCapacity returnConsumedCapacity();

279

Builder returnConsumedCapacity(ReturnConsumedCapacity returnConsumedCapacity);

280

}

281

282

class TransactGetItem {

283

static Builder builder();

284

285

/** Contains the primary key that identifies the item to get */

286

Get get();

287

Builder get(Get get);

288

}

289

290

class Get {

291

static Builder builder();

292

293

/** A map of attribute names to AttributeValue objects that specifies the primary key */

294

Map<String, AttributeValue> key();

295

Builder key(Map<String, AttributeValue> key);

296

297

/** The name of the table from which to retrieve the specified item */

298

String tableName();

299

Builder tableName(String tableName);

300

301

/** A string that identifies one or more attributes of the specified item to retrieve */

302

String projectionExpression();

303

Builder projectionExpression(String projectionExpression);

304

305

/** One or more substitution tokens for attribute names in the ProjectionExpression */

306

Map<String, String> expressionAttributeNames();

307

Builder expressionAttributeNames(Map<String, String> expressionAttributeNames);

308

}

309

310

class TransactGetItemsResponse {

311

/** An ordered array of up to 100 ItemResponse objects */

312

List<ItemResponse> responses();

313

314

/** The capacity units consumed by the entire transaction */

315

List<ConsumedCapacity> consumedCapacity();

316

}

317

318

class ItemResponse {

319

/** Map of attribute data consisting of the data type and attribute value */

320

Map<String, AttributeValue> item();

321

}

322

```

323

324

**Usage Example:**

325

326

```java

327

// Get multiple related items atomically

328

List<TransactGetItem> transactItems = List.of(

329

TransactGetItem.builder()

330

.get(Get.builder()

331

.tableName("Users")

332

.key(Map.of("userId", AttributeValue.builder().s("user123").build()))

333

.projectionExpression("userId, name, email, accountId")

334

.build())

335

.build(),

336

337

TransactGetItem.builder()

338

.get(Get.builder()

339

.tableName("Accounts")

340

.key(Map.of("accountId", AttributeValue.builder().s("acc456").build()))

341

.projectionExpression("accountId, balance, #status")

342

.expressionAttributeNames(Map.of("#status", "status"))

343

.build())

344

.build()

345

);

346

347

TransactGetItemsResponse response = client.transactGetItems(

348

TransactGetItemsRequest.builder()

349

.transactItems(transactItems)

350

.returnConsumedCapacity(ReturnConsumedCapacity.TOTAL)

351

.build()

352

);

353

354

// Process results in order

355

List<ItemResponse> responses = response.responses();

356

Map<String, AttributeValue> user = responses.get(0).item();

357

Map<String, AttributeValue> account = responses.get(1).item();

358

359

if (user != null && account != null) {

360

String userName = user.get("name").s();

361

String balance = account.get("balance").n();

362

System.out.println("User " + userName + " has balance: $" + balance);

363

}

364

```

365

366

### Execute Transaction (PartiQL)

367

368

Execute multiple PartiQL statements as a single atomic transaction.

369

370

```java { .api }

371

/**

372

* Executes multiple PartiQL statements within a transaction block

373

* @param request - The request containing PartiQL statements and options

374

* @return Response containing statement results and consumed capacity

375

*/

376

ExecuteTransactionResponse executeTransaction(ExecuteTransactionRequest request);

377

378

class ExecuteTransactionRequest {

379

static Builder builder();

380

381

/** The list of PartiQL statements representing the transaction to run */

382

List<ParameterizedStatement> transactStatements();

383

Builder transactStatements(Collection<ParameterizedStatement> transactStatements);

384

385

/** Set this value to get remaining results, if NextToken was returned in the previous response */

386

String nextToken();

387

Builder nextToken(String nextToken);

388

389

/** Providing a ClientRequestToken makes the call idempotent */

390

String clientRequestToken();

391

Builder clientRequestToken(String clientRequestToken);

392

393

/** Determines the level of detail about consumed capacity returned */

394

ReturnConsumedCapacity returnConsumedCapacity();

395

Builder returnConsumedCapacity(ReturnConsumedCapacity returnConsumedCapacity);

396

}

397

398

class ParameterizedStatement {

399

static Builder builder();

400

401

/** A PartiQL statement that can be run against a DynamoDB table */

402

String statement();

403

Builder statement(String statement);

404

405

/** The parameter values for the PartiQL statement, if any */

406

List<AttributeValue> parameters();

407

Builder parameters(Collection<AttributeValue> parameters);

408

409

/** An optional parameter for the ReturnValues on this PartiQL statement */

410

ReturnValuesOnConditionCheckFailure returnValuesOnConditionCheckFailure();

411

Builder returnValuesOnConditionCheckFailure(ReturnValuesOnConditionCheckFailure returnValuesOnConditionCheckFailure);

412

}

413

414

class ExecuteTransactionResponse {

415

/** The response to a PartiQL transaction */

416

List<ItemResponse> responses();

417

418

/** The capacity units consumed by the entire transaction */

419

List<ConsumedCapacity> consumedCapacity();

420

}

421

```

422

423

**Usage Example:**

424

425

```java

426

// Execute multiple PartiQL statements in a transaction

427

List<ParameterizedStatement> statements = List.of(

428

ParameterizedStatement.builder()

429

.statement("UPDATE \"Accounts\" SET balance = balance - ? WHERE accountId = ? AND balance >= ?")

430

.parameters(List.of(

431

AttributeValue.builder().n("100.00").build(), // amount to debit

432

AttributeValue.builder().s("account1").build(), // account ID

433

AttributeValue.builder().n("100.00").build() // minimum balance check

434

))

435

.build(),

436

437

ParameterizedStatement.builder()

438

.statement("UPDATE \"Accounts\" SET balance = balance + ? WHERE accountId = ?")

439

.parameters(List.of(

440

AttributeValue.builder().n("100.00").build(), // amount to credit

441

AttributeValue.builder().s("account2").build() // account ID

442

))

443

.build(),

444

445

ParameterizedStatement.builder()

446

.statement("INSERT INTO \"TransactionLogs\" VALUE {'transactionId': ?, 'amount': ?, 'status': ?}")

447

.parameters(List.of(

448

AttributeValue.builder().s("txn-456").build(),

449

AttributeValue.builder().n("100.00").build(),

450

AttributeValue.builder().s("completed").build()

451

))

452

.build()

453

);

454

455

try {

456

ExecuteTransactionResponse response = client.executeTransaction(

457

ExecuteTransactionRequest.builder()

458

.transactStatements(statements)

459

.clientRequestToken("partiql-txn-456")

460

.returnConsumedCapacity(ReturnConsumedCapacity.TOTAL)

461

.build()

462

);

463

464

System.out.println("PartiQL transaction completed successfully");

465

466

} catch (TransactionCanceledException e) {

467

System.err.println("PartiQL transaction failed: " + e.getMessage());

468

}

469

```

470

471

## Transaction Error Handling

472

473

### Common Transaction Exceptions

474

475

```java { .api }

476

class TransactionCanceledException extends DynamoDbException {

477

/** List of cancellation reasons for each item */

478

List<CancellationReason> cancellationReasons();

479

}

480

481

class TransactionConflictException extends DynamoDbException;

482

483

class TransactionInProgressException extends DynamoDbException;

484

485

class CancellationReason {

486

/** Status code for the result of the cancellation */

487

String code();

488

489

/** Descriptive message for the cancellation */

490

String message();

491

492

/** Item in the request which caused the transaction to get cancelled */

493

Map<String, AttributeValue> item();

494

}

495

```

496

497

**Error Handling Example:**

498

499

```java

500

try {

501

client.transactWriteItems(request);

502

} catch (TransactionCanceledException e) {

503

List<CancellationReason> reasons = e.cancellationReasons();

504

for (int i = 0; i < reasons.size(); i++) {

505

CancellationReason reason = reasons.get(i);

506

if (reason.code() != null) {

507

System.err.println("Item " + i + " failed: " + reason.code() + " - " + reason.message());

508

}

509

}

510

} catch (ValidationException e) {

511

System.err.println("Invalid transaction request: " + e.getMessage());

512

} catch (ProvisionedThroughputExceededException e) {

513

System.err.println("Throughput exceeded, retry with backoff");

514

}

515

```

516

517

## Transaction Best Practices

518

519

### Idempotency

520

521

Always use `clientRequestToken` for idempotent transactions:

522

523

```java

524

String requestToken = UUID.randomUUID().toString();

525

TransactWriteItemsRequest request = TransactWriteItemsRequest.builder()

526

.transactItems(items)

527

.clientRequestToken(requestToken) // Ensures idempotency

528

.build();

529

```

530

531

### Conditional Logic

532

533

Use condition expressions to ensure data integrity:

534

535

```java

536

// Only update if current value meets criteria

537

Update.builder()

538

.updateExpression("SET balance = balance - :amount")

539

.conditionExpression("balance >= :amount AND #status = :active")

540

.expressionAttributeNames(Map.of("#status", "status"))

541

.expressionAttributeValues(Map.of(

542

":amount", AttributeValue.builder().n("100").build(),

543

":active", AttributeValue.builder().s("ACTIVE").build()

544

))

545

.build()

546

```

547

548

### Error Recovery

549

550

Handle partial failures and implement retry logic:

551

552

```java

553

try {

554

client.transactWriteItems(request);

555

} catch (TransactionCanceledException e) {

556

// Analyze cancellation reasons

557

// Implement appropriate retry or compensation logic

558

handleTransactionFailure(e.cancellationReasons());

559

}

560

```