DEV Community

Cover image for How DynamoDB Request Routing Works
DynoTable
DynoTable

Posted on • Originally published at dynotable.com

How DynamoDB Request Routing Works

Every read or write you send hits a fleet of stateless request routers first.
A router hashes your partition key, maps the hash to the storage node that owns
that key's data, and forwards the request there. That one hop is why a key lookup
costs the same whether the table holds a thousand items or a billion.

How does DynamoDB request routing work?

DynamoDB routes every request through a stateless request router fleet that hashes your partition key, maps the hash to the single storage node owning that partition, and forwards the read or write there. Routing is a pure function of the key's hash, so one lookup costs the same whether the table holds a thousand items or a billion.

  • The request router is the front door. It's a stateless fleet that takes your request, hashes the partition key, and routes it to the storage node holding that partition — no scanning, no full-table knowledge needed.
  • The partition key decides everything. Routing is a pure function of the partition key's hash — the same key always routes to the partition that owns it, so GetItem is O(1), not O(table size).
  • One primary, two secondaries. A write lands on the partition's primary node, which acknowledges once a quorum (two of the three replicas) has persisted it.
  • Bad keys defeat the design. A low-cardinality or "hot" partition key funnels traffic to one node — the routing is fine, your key is the problem.

Start with the problem routing solves

Coming from SQL, you picture a query planner: it reads statistics, picks an index,
maybe scans. The cost scales with how much data it touches. That model doesn't fit
a key-value store that has to answer in single-digit milliseconds at any size.

DynamoDB's answer is to make a single-item lookup a direct address, not a
search. The partition key isn't a column you filter on — it's the input to a hash
function that computes where the data physically lives. No statistics, no planner.

That's the trade you accept when you move off relational thinking: you give up
ad-hoc query flexibility and get constant-time addressing in return.

Meet the request router

When a request arrives, it doesn't go straight to storage. It hits a request
router
— a stateless, horizontally scaled fleet that fronts the whole service.
(The USENIX ATC '22 DynamoDB paper describes this request-router fleet.)

The router does three things and holds no data of its own:

  • Authenticates and authorizes the request against IAM.
  • Hashes the partition key to find the partition that owns it.
  • Forwards the request to the storage node for that partition.

Because routers are stateless, the service adds more of them under load. None of
them is a bottleneck and none is a single point of failure — the same property the
2007 Amazon Dynamo paper
built the original system around.

Follow one read through the router

Take a telemetry table for a drone fleet. Items are keyed by DroneId (partition
key) and ReadingTs (sort key), with attributes like BatteryPct and AltitudeM.

You ask for one drone's readings from June 23:

Example Notes
PK = "DRONE#A19F"
SK begins_with "2026-06-23"

Here's what the router does with it. The lead-in below traces the request top to
bottom — read it as one downward flow.

How DynamoDB Request Routing Works

The router hashes DRONE#A19F, maps it to the partition that owns that key, and
forwards the read to that partition's primary storage node, which returns the item.

The key insight: the hash points at one partition out of however many the table
has. The router never looks at other partitions, so adding drones — and partitions
— doesn't slow this lookup down.

Know what a partition actually is

A partition is a unit of storage and throughput. Each one is capped (roughly
10 GB and a fixed slice of read/write capacity), and DynamoDB splits a partition
when it outgrows either limit. Every item with a given partition key starts on one
partition; split-for-heat can later carve that collection by sort-key range (unless
an LSI or a monotonic sort key pins it), which is what still makes a Query over
one partition key cheap.

Each partition is replicated to three storage nodes spread across Availability
Zones: one primary and two secondaries.

Node role Handles Consistency it can serve
Primary All writes; strongly-consistent reads Strong (sees its own latest write)
Secondary Eventually-consistent reads; failover Eventual (may lag the primary)

A write goes to the primary, which acknowledges the write once a quorum (two of the
three replicas) has persisted it. A strongly consistent read is routed to the primary
so it reflects the latest write. An eventually consistent read may be served
by a secondary that hasn't caught up yet — half the cost, possibly stale.

Name the footgun: a hot partition key

Routing is only as good as your partition key. The hash spreads keys evenly, so if
your keys have high cardinality and even traffic, load spreads across all
nodes. Break either property and you get a hot partition.

Say you key that telemetry by Region instead of DroneId. Now every drone in
us-east-1 shares one partition key — so their reads and writes hash to the same
keyspace slot and pile onto one item collection. The router is doing its job
perfectly; you've just funneled the whole fleet at a single partition's capacity.

Warning

A hot key isn't a routing bug — it's a modeling bug. The fix is a higher-cardinality
partition key (or a write-sharding suffix), not more capacity.

You can't watch the router pick a node, but you can design keys that route well.
When you build a key condition in the
Expression Builder, the partition key you put
on the left of PK = … is the exact value the router will hash — keeping that
value high-cardinality is what keeps reads on separate nodes.

How this ties back to your access patterns

Request routing is the mechanism that makes the single-table design
rules non-negotiable: you model around the partition key because the partition key
is the address. It's also why a Query beats a Scan
a Query hits one partition through the router, while a Scan walks every
partition in sequence.

Secondary indexes get their own partitions and their own routing: a
GSI is routed by its own partition key, independent of the
base table's, which is why a GSI can be hot even when the table isn't.

Next steps

Design keys that route to many nodes, not one. Sketch the PK = … condition in the
Expression Builder to see exactly which value
gets hashed, then download DynoTable to run those queries against your
own tables and see exactly what each key condition returns.

Top comments (0)