DynamoDB
Query
Sort Key
Database
NoSQL

dynamodb how to query by sort key only?

System Design practice on Codemia

Work through 120+ system design problems with detailed solutions, from rate limiters to multi-region storage.

Practice system design

Introduction

In DynamoDB, a Query operation is designed around a partition key. That is the core rule to remember. If you only know the sort key value, you cannot query the base table directly unless you have modeled an index where that attribute becomes the partition key for that index.

Why the Base Table Cannot Query by Sort Key Alone

DynamoDB stores items by partition key so the service can distribute data efficiently. A sort key only has meaning inside a single partition. Because of that layout, the Query API requires an equality condition on the partition key, and only then can it apply conditions to the sort key.

So this is not valid on a table whose primary key is pk plus sk:

python
1# This is not a valid DynamoDB query on the base table.
2from boto3.dynamodb.conditions import Key
3
4table.query(
5    KeyConditionExpression=Key("sk").eq("ORDER#1001")
6)

The missing piece is pk. Without it, DynamoDB does not know which partition to search.

The Correct Fix: Model an Index for the Access Pattern

If you need to look up items by what is currently the sort key, create a global secondary index, or GSI, where that attribute becomes the index partition key.

For example, suppose the base table uses:

  • 'pk as the tenant or user id'
  • 'sk as an order id'

If you also need to fetch by order id alone, add a GSI such as:

  • 'gsi1pk = sk'
  • 'gsi1sk = created_at'

Then query the index instead of the base table.

python
1import boto3
2from boto3.dynamodb.conditions import Key
3
4dynamodb = boto3.resource("dynamodb", region_name="us-east-1")
5table = dynamodb.Table("Orders")
6
7response = table.query(
8    IndexName="gsi1",
9    KeyConditionExpression=Key("gsi1pk").eq("ORDER#1001")
10)
11
12for item in response["Items"]:
13    print(item)

That is a true query because the index now has a partition key that matches your access pattern.

What If You Cannot Add an Index

The fallback is Scan with a filter expression. That can work functionally, but it is not equivalent to a query. DynamoDB still reads the table or index pages and then filters after the read.

python
1import boto3
2from boto3.dynamodb.conditions import Attr
3
4dynamodb = boto3.resource("dynamodb", region_name="us-east-1")
5table = dynamodb.Table("Orders")
6
7response = table.scan(
8    FilterExpression=Attr("sk").eq("ORDER#1001")
9)
10
11print(response["Count"])

Use this only for small tables, admin tools, or one-off maintenance jobs. It does not scale well for request-path traffic.

Data Modeling Guidance

The real lesson is that DynamoDB schema design starts from access patterns, not from a normalized relational shape. Before you create the table, list the questions the application must answer. Each important lookup path should have a direct primary-key or index design behind it.

Also watch for hot partitions. If the attribute you promote into a GSI partition key has low cardinality, many requests may pile onto the same key. In that case, add write sharding or a more selective key design.

A good DynamoDB model often duplicates key attributes on purpose. That is normal in DynamoDB and usually cheaper than forcing the application into scans.

Common Pitfalls

A common mistake is thinking FilterExpression makes Query work without the partition key. It does not. Filters are applied after DynamoDB has already identified the items to read.

Another mistake is creating a GSI with the same lookup problem moved one level over. If you still need to search the index by its sort key alone, you have not fixed the access pattern.

Developers also sometimes try to solve this with PartiQL. PartiQL changes the syntax, not the storage model. The underlying rule about key-based access still applies.

Summary

  • You cannot query a DynamoDB table by sort key alone.
  • A Query requires equality on the partition key of the table or selected index.
  • If you need that lookup, create a GSI where the desired attribute is the index partition key.
  • 'Scan with a filter can work, but it is a last resort and not a scalable query strategy.'
  • Design DynamoDB tables from access patterns first, even if that means duplicating key attributes.

Related reading
Course
Beginner
27 lessons
10 hours
System Design Fundamentals

Build a strong foundation in designing scalable, reliable distributed systems.

View the course
Track what you have practised

A free account saves your progress, solutions and study plan across every problem on Codemia.

System Design practice on Codemia

Work through 120+ system design problems with detailed solutions, from rate limiters to multi-region storage.

Practice system design

All Rights Reserved.