DynamoDB Primary Key

DynamoDB Primary Key Definition

A DynamoDB primary key is the attribute (or pair of attributes) that uniquely identifies every item in a DynamoDB table. It has to be defined when the table is created, every item written to the table must supply a value for it, and it can’t be changed later without deleting the table (or migrating the data into a new one). There’s no default, auto-generated, or nullable primary key the way a relational database might backfill an identity column.

DynamoDB supports exactly two primary key structures: a simple primary key made of a single partition key, or a composite primary key made of a partition key plus a sort key. AWS also uses two older, interchangeable names for these attributes that still show up in documentation, SDKs, and error messages: hash attribute for partition key, and range attribute for sort key.

DynamoDB Primary Key FAQs

DynamoDB Primary Key Types: Simple vs. Composite

The simplest of the DynamoDB primary key types is a single partition key: DynamoDB runs that value through an internal hash function to decide which partition stores the item, and every item in the table must have a distinct partition key value. A People table keyed on PersonID is a typical example that allows a look up of any person directly, but there’s no built-in way to store two people under the same key.

A DynamoDB primary key and sort key together make up a composite primary key. The partition key still determines which partition an item lands on, but many items can now share the same partition key value as long as each has a different DynamoDB primary key sort key value. DynamoDB stores every item sharing a partition key together, sorted by that sort key, which is what makes range queries (begins_with, between, greater-than) possible within a partition — a Music table keyed on Artist (partition) plus SongTitle (sort) can fetch one artist’s whole catalog, or just the songs whose titles fall in a given range. Partitions that trigger large or hot item alerts might be split across partitions on a sort-key boundary.

DynamoDB Primary Key Types

Aspect Simple Primary Key (Partition Key Only) Composite Primary Key (Partition Key + Sort Key)
Attributes 1 (partition key) 2 (partition key + sort key)
Uniqueness rule Every partition key value must be unique Only the partition key + sort key combination must be unique
Query pattern Direct lookup by partition key Lookup by partition key, optionally narrowed by a sort key range
Example People table: PersonID Music table: Artist (partition) + SongTitle (sort)

DynamoDB Primary Key vs. Partition Key

“DynamoDB primary key vs partition key” is a confusing comparison because a partition key isn’t a competing concept, it’s a component of the primary key. In a simple (partition-key-only) table, the primary key and the partition key are the exact same attribute; there’s no difference to describe. In a composite table, the partition key is only the first half: the full primary key is the partition key plus the sort key together, and it’s that pair (not the partition key alone) that has to be unique per item.

So the practical distinction is scope. “Primary key” is the umbrella term for whatever attribute or attribute pair uniquely identifies an item. “Partition key” refers specifically to the piece DynamoDB hashes to pick a physical partition, it’s always present in a primary key, but it’s the entire primary key only when the table has no sort key.

DynamoDB Primary Key vs. Sort Key

The sort key is optional, and it only exists as the second half of a composite primary key. DynamoDB has no table structure with a sort key and no partition key. Unlike the partition key, the sort key plays no part in deciding physical storage location: two items with the same partition key land in the same partition. Its job is purely to order and filter the items that already share a partition key.

That asymmetry is the real answer to “DynamoDB primary key vs sort key”: a primary key can stand alone (as just a partition key) and is required on every table, while a sort key can never stand alone and is required on none — it’s only ever an optional second piece that extends a primary key from simple to composite.

DynamoDB Primary Key Attributes and Data Types

DynamoDB primary key attributes must be scalar (String, Number, or Binary) and nothing else; a list, map, set, or nested JSON document can be a regular attribute but never a key attribute. AWS also caps the size of key values: a partition key value can be up to 2,048 bytes, and a sort key value up to 1,024 bytes. Attribute names follow their own rules: UTF-8, case-sensitive, and best kept short, since longer names cost more read/write capacity on every item that includes them, as well as tallying for storage purposes.

“DynamoDB primary key unique” describes the combination, not each individual piece: in a composite table, the partition key value by itself can repeat across many items, it’s the partition key plus sort key pairing that has to be distinct. That trips up teams coming from relational databases, where a single-column primary key is expected to be unique on its own. Key values are also immutable once an item is written: there’s no UpdateItem call that changes a key attribute on an existing item, so changing an item’s identity means deleting the old item and writing a new one under the new key.

AWS DynamoDB Primary Key Examples

An aws DynamoDB primary key is declared at table-creation time through AttributeDefinitions (the key attribute’s name and scalar type) and KeySchema (which attribute is HASH — the partition key — and which, if any, is RANGE — the sort key). A DynamoDB primary key example for a simple key needs just one AttributeDefinitions entry and one KeySchema entry with KeyType HASH; a composite key adds a second AttributeDefinitions entry and a second KeySchema entry with KeyType RANGE.

A DynamoDB primary key cloudformation template expresses the same two blocks as a resource definition. A table with a composite primary key of CustomerId (partition) and OrderDate (sort) looks like this:

AWS::DynamoDB::Table:

  KeySchema:

    – AttributeName: CustomerId

      KeyType: HASH

    – AttributeName: OrderDate

      KeyType: RANGE

  AttributeDefinitions:

    – AttributeName: CustomerId

      AttributeType: S

    – AttributeName: OrderDate

      AttributeType: S

AttributeDefinitions only needs to list attributes that are used as keys — on the base table’s primary key or on a secondary index — not every attribute an item might contain.

Can a DynamoDB Primary Key Auto-Increment?

Not natively. DynamoDB has no equivalent of a relational auto-increment or serial column, so a DynamoDB primary key auto increment behavior has to be built in the application. The two common patterns trade off against each other directly. An atomic counter (a dedicated item whose numeric attribute is incremented with an UpdateItem ADD expression, with the returned value used as the new key) produces clean, sequential IDs, but every insert has to go through that single counter item first, capping insert throughput at whatever one item can handle. The ADD operation on an atomic counter is not idempotent, so retrying a failed operation might cause the counter to skip entries, incrementing further than anticipated with the operation.

The alternative, and the one generally recommended for anything write-heavy, is generating the identifier client-side (a UUID, ULID, or similar) before the PutItem call. That removes the single-item bottleneck entirely, since no two writes have to coordinate through the same counter, at the cost of a key that’s neither sequential nor human-readable.

DynamoDB Primary Key and Multiple Columns: Multi-Attribute Composite Keys

A base table’s primary key is capped at exactly two attributes (a partition key, optionally plus one sort key) and that has never changed. Teams wanting a DynamoDB primary key multiple columns structure to model a third or fourth identifying field have historically had to fake it, concatenating several attributes into one synthetic string (something like TOURNAMENT#id#REGION#region) so a single sort key attribute could stand in for what was really a multi-part key.

In November 2025, AWS shipped multi-attribute composite keys for Global Secondary Indexes, letting a GSI define up to four attributes for its partition key and up to four for its sort key, so an index can be built directly on separate, native-typed fields instead of a concatenated string. It’s worth being precise about the scope, though: this applies to GSIs only — the base table’s own primary key is still exactly one partition key plus, optionally, one sort key.

DynamoDB Primary Key Restrictions Explained

The main DynamoDB primary key restrictions to design around:

Exactly One or Two Attributes:

A base table’s primary key is a single partition key, or a partition key plus one sort key — never three or more. A wider composite-key must to go through a GSI’s multi-attribute keys or a concatenated attribute, not the base table’s own primary key.

Scalar Types Only:

Key attributes must be String, Number, or Binary. Lists, maps, sets, and nested documents can only ever be non-key attributes.

Size Caps:

A partition key value tops out at 2,048 bytes; a sort key value at 1,024 bytes.

Values Are Immutable Once Written:

There’s no UpdateItem path that changes a key attribute on an existing item. Changing an item’s identity means deleting it and writing a new item under the new key.

Uniqueness Applies to the Whole Key, Not Each Piece:

In a composite table, only the partition key + sort key pairing has to be unique — the partition key value alone can repeat across many items, which catches teams used to single-column relational primary keys.

Every Item Needs a Complete Key:

There’s no default, auto-generated, or null value for either key attribute. A PutItem call fails if any key attribute is missing.

DynamoDB Primary Key Best Practices

The DynamoDB primary key best practices that come up most often when a table is first designed:

Design for uniform access, not sequential values:

A partition key built from a timestamp or an incrementing counter concentrates recent writes onto a small number of partitions. Favor values with high cardinality — a customer ID, a UUID — that spread traffic evenly.

Avoid hot partitions before they happen:

A partition key with too few distinct values, or one value that’s disproportionately popular, creates a hot partition that throttles independently of the table’s overall provisioned or on-demand capacity. (See DynamoDB Hot Partition for how this plays out in practice.)

Let the sort key match the query, not just the data:

A sort key built around how the application actually queries — a date, a status, a hierarchical prefix — supports begins_with and between operations directly, instead of forcing a Scan or a client-side filter.

Reach for a secondary index before redesigning the primary key:

When an access pattern doesn’t fit the existing partition key and sort key, a Global or Local Secondary Index (see DynamoDB Secondary Index) is usually the better fix than restructuring the base table’s primary key around every possible query.

The downsides of Global or Local Secondary Indexes is they enforce a 10 GB item collection cap and that Local Secondary Indexes can only be created at table creation time.

Prefer client-generated IDs over an atomic counter at scale:

As covered above, a UUID assigned before the write avoids the single-item bottleneck an incrementing counter creates once write volume grows.

Treat the key schema as effectively permanent:

Because primary key values can’t be edited and the key structure can’t be changed after creation without migrating the table, it’s worth working through every expected read pattern before the first production item is written.

ScyllaDB vs. DynamoDB Primary Key: Composite Keys Without the Two-Attribute Ceiling

DynamoDB’s primary key restrictions (exactly one partition key, at most one sort key, and a workaround-only path to anything wider) are a direct consequence of how it distributes data. ScyllaDB uses a similar partition key concept for the same hashing-and-distribution purpose, but its clustering columns (the equivalent of a sort key)  aren’t capped at one. A table can define several clustering columns, so a naturally multi-part identity (say, region, category, and timestamp) doesn’t need a concatenated string or a separate index to model. Instead, it’s additional clustering columns on the same table.

The same underlying design shows up in how each system handles skewed traffic. A DynamoDB partition key with low cardinality creates a hot partition that throttles independently of the rest of the table; ScyllaDB’s shard-per-core architecture spreads and rebalances load across the cluster more evenly, which softens — though doesn’t eliminate — the impact of an imperfectly chosen key. And where DynamoDB needs a secondary index (and now, for a wide composite index key, its new multi-attribute GSI feature) to serve a query the base table’s primary key can’t answer, ScyllaDB’s richer native key model already covers more of those patterns on the base table itself.

DynamoDB Primary Key FAQs

What is a DynamoDB primary key? 

A DynamoDB primary key is the attribute, or attribute pair, that uniquely identifies every item in a table — either a single partition key, or a partition key plus a sort key. It’s defined when the table is created and can’t be changed afterward without migrating the data.

What’s the difference between a DynamoDB primary key and a partition key?

None, in a simple (partition-key-only) table — the primary key is the partition key. In a composite table, the partition key is only the first half of the primary key; the full primary key is the partition key plus the sort key together.

What’s the difference between a DynamoDB primary key and a sort key?

A primary key is required on every table and can stand alone as just a partition key. A sort key is optional and can never stand alone — it only exists as the second half of a composite primary key, ordering and filtering items that share a partition key rather than affecting where they’re physically stored.

What are DynamoDB primary key restrictions?

A base table’s primary key is capped at one partition key plus, optionally, one sort key; key attributes must be scalar (String, Number, or Binary) with size limits of 2,048 bytes and 1,024 bytes respectively; key values can’t be edited once an item is written; and uniqueness applies to the whole key combination, not each attribute individually.

What are DynamoDB primary key best practices?

Choose partition key values with high cardinality and uniform access rather than sequential or low-cardinality values, design the sort key around actual query patterns, use a secondary index instead of restructuring the primary key when a new access pattern comes up, and prefer client-generated IDs over an atomic counter for high write volume.

Trending NoSQL Resources