AWS
JavaScript
DynamoDB
SDK
UnprocessedItems

How to handle UnprocessedItems using AWS JavaScript SDK dynamoDB?

System Design practice on Codemia

Work through 120+ system design problems with detailed solutions, from rate limiters to multi-region storage.

Practice system design

Overview

When working with DynamoDB using the AWS JavaScript SDK, it's common to perform batch operations such as BatchWriteItem or BatchGetItem. These operations can include up to 25 PutItem or DeleteItem requests and 100 GetItem requests, respectively. However, due to limitations such as size constraints or DynamoDB's capacity settings, not all items in these requests may be processed. This is where handling UnprocessedItems becomes crucial.

UnprocessedItems, as the name suggests, are items that DynamoDB was unable to process in the original request. These can occur for several reasons, and handling them correctly ensures robustness in your application.

Understanding UnprocessedItems

Before diving into the implementation, it’s critical to understand the nature of UnprocessedItems:

  • Capacity Exceedance: If the provisioned throughput limit has been exceeded, some items may remain unprocessed.
  • Size Limit: DynamoDB batches have a size limit, and items exceeding that can result in UnprocessedItems.
  • Internal Issues: Sometimes, transient issues within DynamoDB result in items being left unprocessed.

Handling UnprocessedItems involves reattempting these unprocessed items until they have been successfully written or retrieved.

Handling UnprocessedItems using AWS SDK for JavaScript

Prerequisites

Make sure you have the following prerequisites:

  1. AWS SDK for JavaScript installed in your project:
bash
   npm install aws-sdk
  1. AWS Credentials properly configured:
    • Through the AWS_ACCESS_KEY_ID, AWS_SECRET_ACCESS_KEY environment variables or your AWS credentials file.
  2. DynamoDB table set up with appropriate read/write capacity settings.

Handling in BatchWriteItem

Here's how you'd effectively handle UnprocessedItems in a BatchWriteItem request:

javascript
1const AWS = require('aws-sdk');
2const dynamoDB = new AWS.DynamoDB.DocumentClient();
3
4async function batchWrite(items) {
5    let params = {
6        RequestItems: {
7            'YourTableName': items
8        }
9    };
10
11    let retries = 0;
12    const MAX_RETRIES = 5;
13
14    while (retries < MAX_RETRIES) {
15        const data = await dynamoDB.batchWrite(params).promise();
16
17        if (!data.UnprocessedItems || Object.keys(data.UnprocessedItems).length === 0) {
18            console.log(`All items processed successfully.`);
19            break;
20        }
21
22        console.log(`Retrying unprocessed items: attempt ${retries + 1}`);
23        retries++;
24        params.RequestItems = data.UnprocessedItems;
25    }
26
27    if (retries === MAX_RETRIES) {
28        console.error(`Failed to process some items after ${MAX_RETRIES} retries.`);
29    }
30}
31
32const items = [
33    { PutRequest: { Item: { id: '1', value: 'Item 1' } } },
34    { PutRequest: { Item: { id: '2', value: 'Item 2' } } }
35];
36
37batchWrite(items);

Handling in BatchGetItem

Similarly, to handle UnprocessedItems in a BatchGetItem request:

javascript
1async function batchGet(keys) {
2    let params = {
3        RequestItems: {
4            'YourTableName': {
5                Keys: keys
6            }
7        }
8    };
9
10    let retries = 0;
11    const MAX_RETRIES = 5;
12    let allResults = [];
13
14    while (retries < MAX_RETRIES) {
15        const data = await dynamoDB.batchGet(params).promise();
16        allResults = allResults.concat(data.Responses.YourTableName);
17
18        if (!data.UnprocessedKeys || data.UnprocessedKeys['YourTableName'].Keys.length === 0) {
19            console.log(`All items retrieved successfully.`);
20            break;
21        }
22
23        console.log(`Retrying unprocessed keys: attempt ${retries + 1}`);
24        retries++;
25        params.RequestItems['YourTableName'].Keys = data.UnprocessedKeys['YourTableName'].Keys;
26    }
27
28    if (retries === MAX_RETRIES) {
29        console.error(`Failed to retrieve some items after ${MAX_RETRIES} retries.`);
30    }
31
32    return allResults;
33}
34
35const keys = [
36    { id: '1' },
37    { id: '2' }
38];
39
40batchGet(keys).then(data => console.log(data));

Additional Considerations

  • Backoff Strategy: Implementing an exponential backoff with jitter is recommended to handle retries, especially in high-load scenarios.
  • Error Handling: Ensure that your application logs these errors and handles them according to your use case.
  • Provisioned Throughput: Make sure your table’s provisioned throughput settings align with your use case's demand to minimize unprocessed items.

Summary

The table below summarizes key strategies when handling UnprocessedItems:

AspectStrategy
Reason for UnprocessedItemsCapacity limits, size constraints, internal issues
Retry MechanismUse a loop with a retry count and handle errors
Maximum RetriesConfigure according to your needs (e.g., 5 retries)
Exponential BackoffImplement backoff to prevent rapid retries in case of errors
Logging and MonitoringLog retry attempts and errors to enhance observability
Table Capacity ConsiderationsEnsure your table’s capacity aligns with use cases and expected load

By understanding and properly implementing these strategies, your application can handle UnprocessedItems in DynamoDB effectively, ensuring data consistency and reliability.


Related reading
Course
Beginner
27 lessons
10 hours
System Design Fundamentals

Build a strong foundation in designing scalable, reliable distributed systems.

View the course
Track what you have practised

A free account saves your progress, solutions and study plan across every problem on Codemia.

System Design practice on Codemia

Work through 120+ system design problems with detailed solutions, from rate limiters to multi-region storage.

Practice system design

All Rights Reserved.