Bean & Bark: index a question the key can’t answer
The morning rush is behind you. This one's a standing need, not a fire: every morning the fulfillment team wants every order still processing — across all customers — so they can pack and ship. On the base table that's a Scan, because Status isn't a key. You already know what a partition key buys you; now you'll learn how to add one — a GSI — for a question the table's own key can't answer.
- Turn a filtered Scan into a keyed Query by adding a GSI on the attribute you keep filtering by
- See that a GSI is a second key over the same items — a new access pattern, not a copy of the table
- Understand a GSI is sparse (only items carrying the index keys appear) and eventually consistent
The base key can’t answer this
A partition key answers "which items belong to this customer?" — one partition, one customer. Priya's question cuts across customers: every processing order, wherever it lives. There's no partition to go to, so WHERE Status = 'processing' on the base table reads every item and filters — the same Scan you met in chapter one, run every single morning. The fix isn't a cleverer query; it's a new key. You index the attribute she filters by, and her filter becomes a key condition.
-- give the queue a key: index orders by Status, sorted by dateCREATE GSI "byStatus" ON "BeanAndBark" PARTITION KEY (Status) SORT KEY (Placed) PROJECT ALL That's one statement. It lowers to UpdateTable; DynamoDB auto-backfills the index from the attributes already on your items — no rewrite — and it's queryable the moment it goes ACTIVE. Run it once, and the daily Scan becomes a daily Query. Flip the variants below and watch the strip.
Same queue, both ways — but the base-table Scan read the whole table to find four orders, and the index Query read only the four. A GSI is a second key over the same items: you didn't copy the orders anywhere, you gave DynamoDB a second door into them. Priya's morning export is now a keyed read that costs almost nothing.
- A GSI turns a non-key filter into a key condition:
Statusis a Scan filter on the base table, but a cheap Query onbyStatus. - A GSI is an alternate key over the same items — backfilled for free (
UpdateTable, no item rewrite) and queryable onceACTIVE. It answers a question the base key can't. - GSIs are sparse (only items carrying every index-key attribute are indexed) and eventually consistent (a fresh write appears a moment later).
WHERE Status = 'processing' a Scan on BeanAndBark but a Query on BeanAndBark."byStatus"?byStatus GSI is keyed (Status, Placed). Which items appear in it?BeanAndBark orders by Status, sorted by Placed, with the whole item projected.CREATE GSI statement — a PARTITION KEY, a SORT KEY, and PROJECT ALL.Show solution
CREATE GSI "byStatus" ON "BeanAndBark" PARTITION KEY (Status) SORT KEY (Placed) PROJECT ALL — it lowers to UpdateTable, backfills for free, and is queryable once ACTIVE.CREATE GSI "byStatus" ON "BeanAndBark" PARTITION KEY (Status) SORT KEY (Placed) PROJECT ALL processing order across all customers, most recently placed first.FROM "BeanAndBark"."byStatus"), key on Status, and order by the sort key Placed descending.Show solution
Status = 'processing' against byStatus and sort on the index's Placed sort key — a keyed Query that reads only the queue, not the table.SELECT OrderId, CustomerName, Placed, StatusFROM "BeanAndBark"."byStatus"WHERE Status = 'processing'ORDER BY Placed DESC