Partition keys and sort keys

Amazon DynamoDB · Essentials · 12 min

Choosing the key is the most important design decision for any DynamoDB table and cannot be changed later.

Every table has a primary key, declared at creation and immutable afterwards. It comes in two forms:

  • Simple key: a single partition key (also called hash key). Each value identifies exactly one item, e.g. user_id.
  • Composite key: a partition key plus a sort key (range key). Many items can share a partition key as long as their sort keys differ, e.g. customer_id + order_id.

DynamoDB hashes the partition key to decide which physical partition (storage node) holds the item. All items with the same partition key are stored together, sorted by sort key; this group is called an item collection.

That layout explains the query rules. You can:

  • get one item if you know its full primary key
  • query one item collection: all items for a partition key, optionally narrowed with a sort key condition like =, <, between or begins_with, returned in sort-key order

You cannot efficiently ask "all orders over 100 dollars" across customers without an index, because those items live in different partitions.

Good partition keys have many distinct values that are accessed fairly evenly (user ids, device ids). Sort keys are often made sortable on purpose, such as ISO dates (2025-03-01#A17) or prefixes (ORDER#...), so that range queries return useful slices.

Example

# Table "Orders": partition key customer_id, sort key order_id
#
# customer_id | order_id         | total | status
# ------------+------------------+-------+---------
# c1          | 2025-01-09#A11   | 20    | SHIPPED   <- item collection "c1",
# c1          | 2025-03-01#A17   | 35    | PENDING      stored together, sorted
# c1          | 2025-03-14#A20   | 12    | PENDING      by order_id
# c2          | 2025-02-02#B03   | 99    | SHIPPED   <- lives on another partition
#
# Efficient:  get c1 / 2025-03-01#A17
#             all orders of c1 in March 2025:
#               customer_id = "c1" AND begins_with(order_id, "2025-03")
# Not efficient without an index: all PENDING orders of every customer

Remember

  • Primary key = partition key, or partition key + sort key
  • The partition key's hash decides placement; items sharing it form a sorted item collection
  • Queries target one partition key and can filter/sort on the sort key
  • Design sort keys (dates, prefixes) so range queries return useful slices

Watch out for

  • Using a low-cardinality partition key such as status or country, which concentrates traffic on a few partitions.

Check yourself

  1. A table's key is (customer_id, order_id). Which request can DynamoDB serve efficiently?

Sign in to answer, see the explanations, and get this lesson back as a quick review later.

Official docs: docs.aws.amazon.com/amazondynamodb/latest/developerguide/HowItWorks.CoreComponents.html