How To Use DynamoDB LSIs When Designing A New Table
Here’s how I create my LSIs in every DynamoDB table and why you should too.
One strategy I use whenever creating a new DynamoDB table is to instantly create all of the five available LSIs.
LSIs (local secondary indexes) are indexes you can create on your table to enable additional access patterns.
These indexes let you query data differently — you must use the same partition key as the base table but any other sort key.
This allows you to sort data differently or fetch different data based on the sort key value.
The advantage of LSIs over GSIs is that you are not charged the provisioning costs as you would be charged for GSIs.
Quite often you just need to query the same partition key but with a different sort key value and this is where LSIs are particularly useful.
So why automatically create the 5 LSIs upon table creation?
For two reasons:
LSIs can only be created upon table creation; they cannot be created after the table has been created.
They are free to create (up to 5).
Data Model Demo
Imagine a blog post application that stores blog posts data on a DynamoDB table.
Your app has the following query requirements:
Fetch all posts written by a given author, sorted by date.
Fetch posts written by a given author, sorted by status.
Although we can satisfy these two access patterns with a GSI, an LSI allows us to do this without the provisioning costs.
With your LSIs created, you can model your data as follows to support the above two queries:
//Blog Post Datapk: "author#101#posts",
sk: "post#201",
lsi1sk: "date#2025-07-04T12:00#post#201",
lsi2sk: "published#2025-07-04T12:00#post#201",
...other attributes
With this data model we can satisfy the first access pattern “Get posts written by author 101, sorted by date”:
//Blog Post DynamoDB query
TableName: "blog",
"IndexName": "LSI1",
"KeyConditionExpression": "pk = 'author#101#posts' AND begins_with('lsi1sk', "date#")
This query will return all posts written by author#101 and sorted by date since our data model sorts them by date in the sort keys.
To satisfy our second access pattern “Get posts written by author 101, sorted by status e.g. published”:
//Blog Post DynamoDB query
TableName: "blog",
"IndexName": "LSI1",
"KeyConditionExpression": "pk = 'author#101#posts' AND begins_with(lsi1sk, "published#")
This will return all post items that have the status “published” as well as by date. It acts as a filter by returning only published blog posts.
By passing any status value in our query we can filter different statuses.
Neat. That’s the power of LSIs and secondary indexes in general.
👋 My name is Uriel Bitton and I’m committed to helping you master Serverless, Cloud Computing, and AWS.
🚀 If you want to learn how to build serverless, scalable, and resilient applications, you can also follow me on Linkedin for valuable daily posts.
Thanks for reading and see you in the next one!