Calculate DynamoDB Table Overprovisioned Read And Write Capacity Units Based on Last Month
Code
Here is the JavaScript code to calculate the overprovisioned read and write capacity units for a specific DynamoDB table based on the last month.
const AWS = require('aws-sdk'); const dynamodb = new AWS.DynamoDB({}); const cloudwatch = new AWS.CloudWatch(); async function getTableCapacity(tableName) { const params = { TableName: tableName }; const tableDescription = await dynamodb.describeTable(params).promise(); return { readCapacity: tableDescription.Table.ProvisionedThroughput.ReadCapacityUnits, writeCapacity: tableDescription.Table.ProvisionedThroughput.WriteCapacityUnits, }; } async function getConsumedUnits(tableName, metricName) { const params = { Namespace: 'AWS/DynamoDB', MetricName: metricName, Dimensions: [ { Name: 'TableName', Value: tableName, }, ], StartTime: new Date(Date.now() - 30 * 24 * 60 * 60 * 1000), // last 30 days EndTime: new Date(), Period: 3600, Statistics: ['Average'], }; const data = await cloudwatch.getMetricStatistics(params).promise(); return data.Datapoints.map(datum => datum.Average) .reduce((a, b) => a + b, 0); } async function calculateOverProvisionedUnits(tableName) { const tableCapacity = await getTableCapacity(tableName); const readUnitUsage = await getConsumedUnits(tableName, 'ConsumedReadCapacityUnits'); const writeUnitUsage = await getConsumedUnits(tableName, 'ConsumedWriteCapacityUnits'); console.log(`Overprovisioned Read Capacity Units: ${tableCapacity.readCapacity - readUnitUsage}`); console.log(`Overprovisioned Write Capacity Units: ${tableCapacity.writeCapacity - writeUnitUsage}`); } calculateOverProvisionedUnits('my_table');
Note: Replace 'my_table'
with the name of your DynamoDB table.
Detailed Code Explanation
The script starts by loading the AWS SDK and instantiating DynamoDB and CloudWatch objects.
getTableCapacity()
function describes the table and returns its provisioned throughput.
getConsumedUnits()
function calls CloudWatch to retrieve the average consumed capacity units (read or write, based on the metricName argument) for the last month based on the hourly data.
calculateOverProvisionedUnits()
function calls the above two functions to get the provisioned and consumed capacity units and calculates the difference, i.e., the overprovisioned capacity units.
Expected Output Format
The above JavaScript script logs the overprovisioned Read and Write Capacity Units as a numeric value. There is no JSON output for this script.
Considerations & Caveats
Keep in mind that this script's calculations are based on the provisioned capacity and don't apply to tables using on-demand capacity. Additionally, it assumes that capacity has stayed constant over the past month. If you have changed your table's capacity during this time, this will affect the calculations.
Also, note that DynamoDB sometimes takes capacity units to manage internal operations, which might affect your consumption calculation a bit.
Required IAM permissions and example policy
The IAM Role executing this script requires the following permissions:
- dynamodb:DescribeTable
- cloudwatch:GetMetricStatistics
A basic IAM policy encompassing these permissions would look like:
{ "Version": "2012-10-17", "Statement": [ { "Sid": "VisualEditor0", "Effect": "Allow", "Action": [ "dynamodb:DescribeTable", "cloudwatch:GetMetricStatistics" ], "Resource": "*" } ] }
FAQ
- Does the script work for tables using on-demand capacity?
- No, it only works for tables using provisioned capacity.
- What if I changed my table's capacity in the past month?
- The script does not account for capacity changes, and the calculation would not be accurate.
- What timezone is the script using for last month?
- It uses the UTC timezone.
- Why we choose 'Average' not 'Sum' for the getMetricStatistics Statistics?
- 'Average' gives a more accurate measure of typical capacity usage over the period, while 'Sum' may be skewed by high-usage outliers.