Scale DynamoDB Capacity using CloudWatch Metrics on Java
DynamoDB will happily throttle your writes once you push past the provisioned capacity, so it pays to react before that becomes a problem. In this post I’ll show how to autoscale DynamoDB using the AWS Java SDK, watching CloudWatch and bumping capacity when throttling starts to climb.
The starting point is the connection itself. We open our client and session and grab the DynamoDB table we care about, all through the AWS Java SDK.
AmazonDynamoDB client = AmazonDynamoDBClientBuilder.standard().withRegion(Regions.US_WEST_2).build();
DynamoDB dynamoDB = new DynamoDB(client);
String tableName = "webischia-table";
Table table = dynamoDB.getTable(tableName);
With the table in hand, we turn to CloudWatch for the signal that tells us how things are going. We build a request for the last 10 minutes of metrics and read back the CloudWatch JSON response.
final AmazonCloudWatch cloudWatch =
AmazonCloudWatchClientBuilder.defaultClient();
Dimension instanceDimension = new Dimension();
instanceDimension.setName("TableName");
instanceDimension.setValue("webischia-table");
GetMetricStatisticsRequest request = new GetMetricStatisticsRequest()
.withStartTime(new Date(new Date().getTime() - offsetInMilliseconds))
.withNamespace("AWS/DynamoDB")
.withPeriod(60)
.withMetricName("WriteThrottleEvents")
.withStatistics("Sum")
.withDimensions(Arrays.asList(instanceDimension))
.withEndTime(new Date());
GetMetricStatisticsResult getMetricStatisticsResult = cloudWatch.getMetricStatistics(request);
Double writeCapUnit = table.describe().getProvisionedThroughput().getWriteCapacityUnits().doubleValue();
Out of that response, the number we actually care about is the latest cumulative sum of write throttling.
Double currentSum = getMetricStatisticsResult.getDatapoints().get(0).getSum();
From there it’s just our own logic. In this example, when the cumulative sum climbs past 100, I increase the capacity by 20%.
if(currentSum >=100){
System.out.println("Capacity increased");
try {
table.updateTable(new ProvisionedThroughput((long) 1, (long)(writeCapUnit.longValue() *1.2 )));
System.out.println("Done");
}
catch (Exception e) {
e.printStackTrace();
}
}
And that covers it. If you want this to run every 10 minutes, just wrap it in a loop or run it on a thread.