For agents
accesspatterns.dev for agents and crawlers
accesspatterns.dev teaches DynamoDB data modelling by running real queries on a DynamoDB-compatible engine in the browser. The playground and the model pages run that engine after JavaScript loads, so this page lays the course, the models and the machine-readable files out as plain text you can read without running anything.
The in-browser engine is scored by the same conformance suite that backs dynoxide's native build. Several operations are still missing - transactions, streams, tags, TTL, backups and export, among others - so it is not a like-for-like replacement for the native engine. Where an operation is unimplemented the engine refuses it rather than approximating a result, so treat a missing operation as a gap in this build and not as DynamoDB's own behaviour. Its conformance results are published per run.
Machine-readable
- llms.txt - the course and models as a link list
- llms-full.txt - the full course text, plus every model's key schema, indexes and example rows
- manifest.json - the same, structured: key schema, access patterns and example items per model
- sitemap.xml - every page
The course (27 lessons)
Foundations
What an item is, and how the key addresses it.
- Items, not rows - Two items in one table can have completely different attributes.
- The key is the address - GetItem needs the whole primary key: partition and sort.
Reads and cost
The three ways to read, and what each one charges you.
- One query, a whole collection - Items that share a partition key are read together in one Query.
- The sort key is a query language - Conditions on the sort key narrow a Query before it reads, for free.
- A filter is not an index - A FilterExpression runs after the read: you pay for everything scanned.
- Read the latest first - A sorted timestamp makes 'the most recent' a direction, not a sort in your code.
- Read a page, keep the bookmark - Limit caps a page; LastEvaluatedKey is the bookmark you feed back to resume.
Writing data
Putting, changing, and guarding items.
- PutItem replaces - PutItem writes a whole item and overwrites any item with the same key.
- UpdateItem edits in place - UpdateItem changes named attributes and can increment a counter atomically.
- Claim it, or fail - A ConditionExpression lets a write happen only if the data still allows it.
- No silent clobbers - A version check lets an update land only if nobody changed the item since you read it.
Modelling relationships
One-to-many, secondary indexes, and sparse indexes.
- Model a one-to-many with one partition - A parent and its children share a partition key, so one Query fetches them together.
- One key, every level - A path in the sort key lets one begins_with read any level of a hierarchy.
- A different key for a different question - A secondary index re-keys your items so you can Query them on a new axis.
- Traverse a relationship both ways - An index that swaps the partition and sort keys reads the same edges from the other side.
- Absence as a filter - An item appears in an index only if it has the index's key, so leaving the key off filters it out.
- Keep the total where you read it - A denormalised count on the parent turns an aggregate into a single GetItem.
Single-table design
One table, one index, many access patterns.
- One index, many questions - Different entity types share generic index keys, so one index serves several access patterns.
- An index holds only what you project - Projection decides which attributes an index carries, trading storage against an extra read.
- One table, an application's worth of questions - Generic keys and one overloaded index answer five access patterns with no join and no scan.
Vector search
Storing an embedding beside the item it describes, and searching it.
- A vector is just an attribute - A vector is a list of numbers on an item. An index is what makes it searchable.
- Three ways to be near - The metric is a decision you make once, at index creation, and cannot change.
- The wrong model still answers - Query with a different model from the one that wrote the vectors and you get a confident wrong answer, silently.
- Two read paths, one item - The same items answer "what happened last" and "what is relevant", through two different reads.
- You can only filter on what you declared - A vector index will only filter on attributes you nominated when you created it, with = and nothing else.
- Find one chunk, read its neighbours - Search narrow, then widen with the keys you already have.
- When similarity is the wrong question - Some questions are not similarity questions, and a vector index answers them badly.
The models
- URL Shortener - A hash-only table keyed by short code, the classic key-value lookup.code (S) (hash-only, no sort key)
- Feature Flags - Flag values per environment, read one at a time or all at once.PK (S) / SK (S)
- Web Sessions - Server-side sessions keyed by token, expired by the database.PK (S) (hash-only, no sort key)
- Idempotency Keys - A conditional write that makes a retried request safe.PK (S) (hash-only, no sort key)
- Account & Settings - Two entity types under one key, told apart by the sort key.PK (S) / SK (S)
- SaaS Multi-Tenant - Organisations and their members in one table, isolated by partition.PK (S) / SK (S)
- Customer Orders - A customer's order history, newest first, in one partition.PK (S) / SK (S)
- Notifications Feed - A per-user feed read a page at a time, with unread as a sparse marker.PK (S) / SK (S)
- Sensor Readings - Append-only device telemetry, read by time window and expired by TTL.PK (S) / SK (S)
- Change & Audit Log - An append-only history beside the current state it explains.PK (S) / SK (S)
- Folder Tree - A file hierarchy encoded in the sort key, so a subtree is one read.PK (S) / SK (S)
- Work Orders - Several query dimensions packed into one sort key, with no index.PK (S) / SK (S)
- Product Autocomplete - Type-ahead from a sort key, without a search service.PK (S) / SK (S)
- Support Ticket Queue - A worklist that maintains itself, because closing a ticket leaves the index.PK (S) (hash-only, no sort key)
- Stock Counter - A counter that decrements atomically and refuses to go negative.PK (S) / SK (S)
- Fleet Registry - Two attributes that must both be unique, enforced with lock items.PK (S) (hash-only, no sort key)
- Shared Config Document - One item per document, and what happens as it approaches 400 KB.PK (S) / SK (S)
- Account Ledger - Money moved between two accounts, or not moved at all.PK (S) / SK (S)
- Trending Counter - One hot count, spread across shards so no single key takes the load.PK (S) (hash-only, no sort key)
- Store Locator - Finding what is nearby, using a geohash as a sort key.PK (S) (hash-only, no sort key)
- Contacts CRM - One index answering two different questions.PK (S) / SK (S)
- Commerce Capstone - Four entity types, one table, no joins and no scans.PK (S) / SK (S)
- Game Leaderboard - Per-game high scores, ranked with a secondary index on score.PK (S) / SK (S)
- Maintainers & Projects - A many-to-many between people and projects, read from either side.PK (S) / SK (S)
- Agent Memory Store - One conversation log, read two ways: by recency and by meaning.PK (S) / SK (S)
- RAG Chunk Store - Find one chunk by meaning, then read its neighbours by key.PK (S) / SK (S)
- Tenant Incident Triage - Search one tenant's incidents by meaning, filtered on what you declared.PK (S) / SK (S)
- More Like This - Recommendations with no embedding call on the read path.PK (S) (hash-only, no sort key)
- Catalogue Semantic Search - A vector index and a GSI on one table, answering different questions.PK (S) / SK (S)
Related projects
- dynoxide - the engine this site runs, version 1.0.0
- Parity Suite - a neutral DynamoDB conformance suite (a sibling project)
- Martin Hicks - the author