Skip to main content

DynamoDB Batch Operations in C#

Perform efficient bulk operations on DynamoDB using FluentDynamoDB. Batch operations allow you to read or write multiple items in a single request, significantly reducing API calls and improving throughput. This guide demonstrates batch writes and batch gets using the three API patterns.

Batch Write Operations

// Put multiple items in a single batch
await DynamoDbBatch.Write
.Add(userTable.Put(new User { UserId = "user1", Name = "Alice" }))
.Add(userTable.Put(new User { UserId = "user2", Name = "Bob" }))
.Add(userTable.Put(new User { UserId = "user3", Name = "Charlie" }))
.ExecuteAsync();

Mixed Put and Delete

// Combine put and delete operations
await DynamoDbBatch.Write
.Add(userTable.Put(newUser))
.Add(userTable.Delete("oldUserId"))
.Add(orderTable.Put(newOrder))
.Add(orderTable.Delete("customerId", "oldOrderId"))
.ExecuteAsync();

Multi-Table Batch Write

// Write to multiple tables in one batch
await DynamoDbBatch.Write
.Add(userTable.Put(user))
.Add(orderTable.Put(order))
.Add(auditTable.Put(auditEntry))
.ExecuteAsync();

Batch Get Operations

// Get multiple items with tuple destructuring
var (user, order) = await DynamoDbBatch.Get
.Add(userTable.Get(userId))
.Add(orderTable.Get(orderId))
.ExecuteAndMapAsync<User, Order>();

Console.WriteLine($"User: {user?.Name}");
Console.WriteLine($"Order: {order?.Status}");

Batch Get with Projection

// Retrieve only specific attributes
var (user1, user2, user3) = await DynamoDbBatch.Get
.Add(userTable.Get("user1").WithProjection(x => new { x.Name, x.Email }))
.Add(userTable.Get("user2").WithProjection(x => new { x.Name, x.Email }))
.Add(userTable.Get("user3").WithProjection(x => new { x.Name, x.Email }))
.ExecuteAndMapAsync<User, User, User>();

Batch Get with Index Access

// Access results by index for larger batches
var response = await DynamoDbBatch.Get
.Add(userTable.Get("user1"))
.Add(userTable.Get("user2"))
.Add(userTable.Get("user3"))
.Add(orderTable.Get("order1"))
.ExecuteAsync();

var user1 = response.GetItem<User>(0);
var user2 = response.GetItem<User>(1);
var user3 = response.GetItem<User>(2);
var order = response.GetItem<Order>(3);

Result Access Patterns

FluentDynamoDB provides multiple ways to access batch get results:

var response = await DynamoDbBatch.Get
.Add(userTable.Get("user1"))
.Add(userTable.Get("user2"))
.Add(userTable.Get("user3"))
.Add(orderTable.Get("order1"))
.ExecuteAsync();

// Single item by index
var user1 = response.GetItem<User>(0);

// Multiple items by indices
var users = response.GetItems<User>(0, 1, 2);

// Contiguous range of items
var allUsers = response.GetItemsRange<User>(0, 2);

// Check total count
Console.WriteLine($"Retrieved {response.Count} items");

Handling Unprocessed Items

DynamoDB may not process all items due to capacity limits. Always check for unprocessed items:

// Batch write with unprocessed item check
var writeResponse = await DynamoDbBatch.Write
.Add(userTable.Put(user1))
.Add(userTable.Put(user2))
.ExecuteAsync();

if (writeResponse.UnprocessedItems.Count > 0)
{
Console.WriteLine("Some items were not processed - implement retry logic");
}

// Batch get with unprocessed key check
var getResponse = await DynamoDbBatch.Get
.Add(userTable.Get("user1"))
.Add(userTable.Get("user2"))
.ExecuteAsync();

if (getResponse.HasUnprocessedKeys)
{
Console.WriteLine("Some keys were not processed - implement retry logic");
}

Batch Limits

OperationLimit
BatchWriteItem25 items per request
BatchGetItem100 items or 16MB per request

For larger datasets, chunk your requests:

// Process items in chunks of 25
foreach (var chunk in users.Chunk(25))
{
var batch = DynamoDbBatch.Write;
foreach (var user in chunk)
{
batch.Add(userTable.Put(user));
}
await batch.ExecuteAsync();
}

Learn More