Primary key uniquely identifies each item in a DynamoDB table and can be simple (a partition key only) or composite (a partition key combined with a sort key).
Partition key portion of a table’s primary key determines the logical partitions in which a table’s data is stored, which in turn affects the underlying physical partitions.
Partition key should have many unique values.
Distribute reads / writes uniformly across partitions to avoid hot partitions
Store hot and cold data in separate tables
Consider all possible query patterns to eliminate the use of scans and filters.
Choose a sort key depending on the application’s needs.
Avoid hot keys and hot partitions – a partition key design that doesn’t distribute I/O requests evenly can create “hot” partitions that result in throttling and use the provisioned I/O capacity inefficiently.
Use GSIs for finer control over throughput or when your application needs to query using a different partition key.
Can be used for eventually consistent read replicas – set up a global secondary index that has the same key schema as the parent table, with some or all of the non-key attributes projected into it.
Project fewer attributes – As secondary indexes consume storage and provisioned throughput, keep the index size as small as possible by projecting only required attributes as it would provide greater performance
Keep the number of indexes to a minimum – don’t create secondary indexes on attributes that aren’t queried often. Indexes that are seldom used contribute to increased storage and I/O costs without improving application performance.
Sparse indexes – DynamoDB indexes are Sparse and it writes a corresponding index entry only if the index sort key value is present in the item. If the sort key doesn’t appear in every table item, the index will do contain the item.
Large Items and Attributes
DynamoDB currently limits the size of each item (400 KB) that is stored in a table, which includes both attribute names and values binary length.
Use shorter (yet intuitive!) attribute names
Keep item size small.
Use compression (GZIP or LZO).
Split large attributes across multiple items.
Store metadata in DynamoDB and large BLOBs or attributes in S3.
Querying and Scanning Data
Avoid scans and filters – Scan operations are less efficient than other operations in DynamoDB. A Scan operation always scans the entire table or secondary index. It then filters out values to provide the result, essentially adding the extra step of removing data from the result set.
Use eventual consistency for reads.
Time Series Data
Use a table per day, week, month, etc for storing time series data – create one table per period, provisioned with the required read and write capacity and the required indexes.
Before the end of each period, prebuild the table for the next period. Just as the current period ends, direct event traffic to the new table. Assign names to the tables that specify the periods they have recorded.
As soon as a table is no longer being written to, reduce its provisioned write capacity to a lower value (for example, 1 WCU), and provision whatever read capacity is appropriate. Reduce the provisioned read capacity of earlier tables as they age.
Archive or drop the tables whose contents are rarely or never needed.
Dropping tables is the fastest, simplest and cost-effective method if all the items are to be deleted from the table, without spending time in scanning and deleting each item.
Other Best Practices
Burst Capacity reserves a portion of unused capacity (5 mins.) for later bursts of throughput to handle usage spikes.
Adaptive capacity helps run imbalanced workloads indefinitely. It minimizes throttling due to throughput exceptions and reduces cost by enabling you to provision only the needed throughput capacity.
Deletion protection can keep the tables from being accidentally deleted.