DynamoDB Deep Dive - by Adlet Balzhanov - The True Engineer
SubscribeSign in
DynamoDB Deep Dive<br>Most “DynamoDB knowledge” online is too generic/too long to help.
Adlet Balzhanov<br>Jul 19, 2026
Share
I’ve been living inside DynamoDB for a while now, building and scaling a distributed system on AWS that has to survive couriers, customers, and agents all hammering it at once (at a scale of 10+ million orders per day).<br>Along the way, I collected a pile of notes with, let's say, my best practices. Half of them learned the easy way (reading docs), half learned the hard way (staring at a CloudWatch, Grafana at 2am wondering why one partition is on fire while the rest of the table is bored).<br>This is the cleaned-up version of my notes. Just the things I actually needed to know. I assume if you are reading this, you are already familiar with the basic DynamoDB concepts, so we will not stop there.<br>eventual vs strong consistency
By default, DynamoDB gives you eventual consistency. You write, and a moment later every replica has the update. Almost always fast enough, almost always correct enough, cheap too.<br>If “almost” isn’t good enough for you, there’s ConsistentRead: true . Add that to a GetItem, Query, or Scan (!! do not use Scan on production, it is bad, it is expensive), and DynamoDB routes your read through the primary replica that’s guaranteed to have every successful write applied. You get the freshest possible data.<br>Of course, it costs more to you. Literally, double the RCUs, and it can be slower because there’s coordination happening across nodes instead of just reading whatever replica is closest. And it’s not available everywhere. Base tables and LSIs support it, GSIs don’t. If your access pattern needs strong consistency, that alone might decide whether you reach for an LSI or a GSI.<br>My rule of thumb: default to eventual, and only reach for strong consistency when the alternative is a genuinely bad user experience.<br>LSI vs GSI
This is the one that trips people up the most, because on paper LSIs and GSIs look like siblings. In practice they behave very differently, and one of them is way less forgiving.<br>LSI (Local Secondary Index)<br>Same partition key as the base table, different sort key. That’s the whole point. It lets you resort items within a partition to support another data access pattern.
Can be strongly consistent. GSIs can never do this, at least now (July 2026).
Must be created at table creation time. You cannot bolt one on later, and you cannot delete one once it exists. Get this wrong on day one and you’re rebuilding the table.
Shares the base table’s provisioned throughput. No separate capacity to manage, but also no isolation. A hot LSI can starve your base table.
Everything sharing a partition key (the “item collection”) is capped at 10GB total, across the base table and all its LSIs combined. This is easy to forget until you hit it.
GSI (Global Secondary Index)<br>Independent partition key and sort key. You can query across the entire table, not just within a partition.
Add or remove them whenever you want.
Own provisioned throughput, separate from the base table.
Eventually consistent only.
So the real decision isn’t “which is more powerful”. GSIs almost always win on flexibility. If you’re not 100% sure, use a GSI. You can always add another one next sprint. You can’t undo an LSI.<br>partition keys
DynamoDB spreads your data across partitions based on the hash of your partition key. If your key distributes evenly, life is good. Throughput scales roughly linearly and nothing gets hot. If it doesn’t, one partition eats all the traffic while its neighbors sit idle, and you throttle even though your table-level metrics look fine.<br>So, always aim for a pattern where your partition key is random enough and spreads writes/reads across shards (e.g., based on a random user_id, order_id, or a combination of the two).<br>DynamoDB does have your back to some extent. Adaptive capacity automatically borrows RCUs/WCUs from cooler partitions to help a temporarily hot one. It’s a real safety net, not marketing copy. But adaptive capacity is for temporary hot spots. If one key is permanently the busiest thing in your system (think: one massive celebrity user), no amount of borrowing saves you. You need a synthetic key strategy, like sharding that one key into KEY#0 through KEY#9 and fanning reads back out on the query side.<br>TTL
Set an expiry timestamp attribute on an item, and DynamoDB will delete it for you once it passes. You don't need a cron job or a batch cleanup script. No cost of storing temporary state forever. If you've got Streams enabled, those TTL deletions still show up in the stream. Just note the retention is a fixed 24 hours, not configurable so you can react to expirations just like any other write. If you need to hold onto that history longer, Kinesis Data Streams for DynamoDB is a separate, opt-in option that lets you configure retention anywhere from 24 hours up to 365 days.<br>the...