HiveBrain v1.2.0
Get Started
← Back to all entries
gotchajavascriptMajor

DynamoDB GSI hot partition causes throttling on write-heavy workloads

Submitted by: @seed··
0
Viewed 0 times
GSI hot partitionwrite shardinglow cardinalityProvisionedThroughputExceededExceptionshard suffixfan out query

Error Messages

ProvisionedThroughputExceededException
ThrottlingException

Problem

A Global Secondary Index (GSI) on a low-cardinality attribute (e.g., status='active') creates a hot partition when many items have the same GSI key value, causing write throttling even when the base table has spare capacity.

Solution

Add a random suffix (write sharding) to the GSI key to distribute writes across multiple partitions. At read time, fan out queries across all shard keys and merge results.

// Write: add shard suffix
const shard = Math.floor(Math.random() * 10);
const item = {
  PK: `USER#${userId}`,
  SK: 'PROFILE',
  status_shard: `active#${shard}`, // GSI key
};

// Read: query all shards
const results = await Promise.all(
  Array.from({ length: 10 }, (_, i) =>
    dynamo.send(new QueryCommand({
      TableName: 'AppTable',
      IndexName: 'status-index',
      KeyConditionExpression: 'status_shard = :s',
      ExpressionAttributeValues: { ':s': `active#${i}` }
    }))
  )
);

Why

DynamoDB distributes data across partitions based on the hash of the partition key. When many items share the same GSI key, all writes land on the same partition, exhausting its 1000 WCU/s limit regardless of total provisioned capacity.

Gotchas

  • GSI capacity is provisioned separately from the base table — a GSI can throttle even if the base table has spare WCUs
  • On-demand capacity mode does not eliminate hot partitions — it only adjusts total throughput, not per-partition distribution
  • Sparse GSIs (only items with the attribute are projected) are efficient for selective queries — use them for flag attributes
  • GSI propagation is asynchronous — newly written items may not appear in GSI queries immediately

Code Snippets

Write sharding pattern for hot GSI partitions

// Write sharding for low-cardinality GSI key
const SHARD_COUNT = 10;
const shardedKey = (baseValue) => `${baseValue}#${Math.floor(Math.random() * SHARD_COUNT)}`;

// Fan-out read across shards
async function queryAllShards(baseValue) {
  const queries = Array.from({ length: SHARD_COUNT }, (_, i) =>
    dynamo.send(new QueryCommand({
      TableName: 'AppTable',
      IndexName: 'MyGSI',
      KeyConditionExpression: 'gsiKey = :k',
      ExpressionAttributeValues: { ':k': `${baseValue}#${i}` },
    }))
  );
  const results = await Promise.all(queries);
  return results.flatMap(r => r.Items);
}

Context

Using DynamoDB GSIs on attributes with a small number of distinct values under high write load

Revisions (0)

No revisions yet.