docker run --rm -p 8000:8000 amazon/dynamodb-local -jar DynamoDBLocal.jar -inMemory -cors https://geekychris.github.io
DynamoDB single-table modeller
Design a DynamoDB single table — entities with key templates, GSIs and LSIs — see its items grouped by partition, check every access pattern (which GetItem or Query serves it, on which index, and how much it reads to return what), estimate capacity and on-demand against provisioned cost, and export to NoSQL Workbench, CloudFormation or CDK; with a DynamoDB engine in the page and a client for DynamoDB Local.
Added
Works with
- NoSQL data modelling Databases and streamingcompare the key-value model of an application with document, wide-column and graph models before building its single table
How to use it
In DynamoDB you design the keys from the questions the application will ask, not from the entities. This page lets you write those questions down next to the design and check them. Everything runs in the page: a DynamoDB engine (PutItem, GetItem, Query, Scan, UpdateItem, DeleteItem, batch and transaction calls, with the real expression languages) holds the model’s sample items, and each check is a real request run on it.
How to use it
-
Model — start from an example (an online shop, an employee directory, a game leaderboard, multi-tenant documents) or a blank model. Name the table’s partition and sort key (usually the generic
PKandSK), add global and local secondary indexes, then describe each entity: its attributes, a key template for every key attribute, and a few sample items as JSON. Templates are literals with{attribute}placeholders —CUSTOMER#{customerId},ORDER#{orderDate}#{orderId},{score:010}(zero-padded to ten digits so numbers sort as text). Leave a template empty and the entity stays out of that index. Edit the model as JSON shows the whole model; Save model file and Open keep it as a file. -
Items — the sample items as DynamoDB stores them, grouped by partition key and sorted by sort key, for the table or any index (like NoSQL Workbench’s facets view). An item without an index’s key attributes is not in that index; the count says how many are missing. Click an item for its DynamoDB JSON and size. Full screen (F) gives the view the whole screen.
-
Access patterns — one card per question: which entities it returns, the attributes you look it up by (equality), an optional range or order on one attribute, extra filters, the order and limit, requests per second, and whether it needs strongly consistent reads. The check tries the table and every index and picks the best: a GetItem when the whole primary key is known, a Query with
=,begins_withorBETWEENon the sort key when part of it is, a Query on the whole item collection when several entities share a partition, and a Scan (flagged as a problem) when no index has a partition key you can compute. It shows the request (open it in the console), items returned against items read, read units, and warnings: filter waste, a range that is not served by the sort key, constant partition keys (hot partitions), consistent reads asked of a GSI, and projections that need a second read. -
Capacity & cost — read and write units for an item size; the model’s traffic from the patterns' rates and the entities' write rates (each index an item is in is another write); on-demand against provisioned cost per month, with a chart of both against the peak-to-average ratio (provisioned has to be sized for the peak); and every warning, including write hot spots, items over 400 KB and LSI item collections.
-
Console — send any request as JSON (Ctrl/⌘+Enter) to the built-in engine or to DynamoDB Local. Example request fills in one for the chosen operation from the model; Create the model’s table and Load the sample items set up the design on either. Responses show
Count,ScannedCount,LastEvaluatedKeyand consumed capacity. -
Export — NoSQL Workbench data model JSON (format 3.0: the table, GSIs, a facet per entity with the key templates as aliases, and the sample data), CloudFormation YAML, AWS CDK (TypeScript,
TableV2), the CreateTable request, and BatchWriteItem requests. NoSQL Workbench files can also be opened in the Model tab (facets become entities, the data comes as items).
Single-table patterns in the examples
-
Adjacency list / item collection (Online shop): a customer’s profile and orders share the partition
CUSTOMER#…; one Query returns the customer page,begins_with(SK, "ORDER#")only the orders. -
Composite sort key (
ORDER#{orderDate}#{orderId}): orders come back in date order, and a date range is aBETWEENon the sort key. A hierarchical key (DOC#{path}#{docId}, multi-tenant documents) lists a folder at any depth withbegins_with. -
Inverted index (GSI1 = SK/PK swapped, or a second template): order items found by product.
-
Sparse index: only open orders have
openFlag, so GSI2 holds only them and is cheap to read and to write; the game’s Badges index holds only badged scores. -
GSI overloading (Employee directory, after the Developer Guide’s "Overloading global secondary indexes"): the GSI’s sort key
Dataholds a name for one entity, a date for another and a city for a third, so one index answers several questions. -
Write sharding: the game’s global leaderboard has one constant partition (
ALL); at 1,500 writes a second it is over a partition’s 1,000 write units, and the check says so.
Rules this page follows
-
Expressions as in the Developer Guide: condition, filter, key condition, update and projection expressions with
#nameand:valueplaceholders; comparators,BETWEEN,IN,AND/OR/NOT(precedence NOT, AND, OR),attribute_exists,attribute_not_exists,attribute_type,begins_with,contains,size;SETwith+/-,if_not_existsandlist_append,REMOVE(list elements too),ADD(numbers and sets),DELETE(sets). Reserved words used without a#placeholder, unused or undefined placeholders, overlapping update paths, updating a key attribute, and key conditions DynamoDB rejects (>on the partition key,OR,contains,<>, a non-key attribute, three conditions) all fail with the service’s messages. -
Item size: attribute names plus values; strings by UTF-8 bytes; numbers about one byte per two significant digits plus one; booleans and null one byte; lists and maps 3 bytes plus one per element. Items over 400 KB are refused.
-
Capacity: one read unit is a strongly consistent read of up to 4 KB (eventually consistent: half; transactional: double); one write unit a write of up to 1 KB (transactional: double). A Query or Scan rounds the total size of the items it read up to 4 KB once; a write costs the larger of the old and new item, and again on each index whose copy changes (twice when an index key changes).
Limitcounts items read before the filter, and a page stops at 1 MB. -
Prices: us-east-1, Standard table class, from AWS’s pricing pages (checked 17 October 2026, unchanged since the 1 November 2024 on-demand price cut): on-demand $0.625 per million write request units and $0.125 per million read request units; provisioned $0.00065 per WCU-hour and $0.00013 per RCU-hour; storage $0.25 per GB-month after 25 GB. They can be edited on the page.
The engine was checked request by request against DynamoDB Local: the same items, counts, keys, returned attributes and error types for 30 requests covering every operation above.
Connecting to DynamoDB Local
The console (and Run every pattern on DynamoDB Local on the Access patterns tab) talks to DynamoDB Local over its HTTP JSON API, signing each request with Signature Version 4 in the page. Use dummy keys (Local accepts any); they stay in memory and are never saved or put into links. Three routes:
-
Direct — the page calls the endpoint itself. Start Local with this page’s origin on its CORS list (its default,
-cors *, sends noAccess-Control-Allow-Originheader, so a browser refuses the reply): -
⚡ App TCP relay — through the gitwebsite app’s companion: the page speaks HTTP/1.1 over the app’s TCP relay, so no CORS setting is needed. Add the endpoint’s
host:port(such as127.0.0.1:8000) to the app’s TCP allow-list. -
⚡ App LAN relay — companion v1.2’s HTTP relay to hosts on your LAN (the app asks the first time a page reaches a new host). The relay has to pass DynamoDB’s
X-Amz-TargetandX-Amz-Dateheaders.
AWS itself. This page refuses *.amazonaws.com endpoints: it will not ask for real AWS keys.
Signing in the gitwebsite app with a profile it keeps (as it does for S3), so that keys never
enter a web page, is planned; until then use the AWS CLI or SDKs with the exported requests.
Linking to an example
The model is kept in this browser and travels in share links. Hand-written links:
| Parameter | Meaning |
|---|---|
|
|
|
the index shown on the Items tab ( |
The tab is the #hash: /tools/dynamodb/?example=shop#patterns, /tools/dynamodb/?example=game#cost,
/tools/dynamodb/?example=shop&ix=GSI2#items.
Limits
-
Numbers are compared and added as JavaScript numbers (about 15–17 significant digits), not DynamoDB’s 38-digit decimals; binary values are base64 strings.
-
The engine is one process: no partitions, throttling, streams, TTL deletion, PartiQL, or the legacy
KeyConditions/AttributesToGetparameters. Scan `Segment`s split items by a hash of the partition key. Only about 570 reserved words are checked as the service does. -
The checker reasons from key templates and the sample items: it cannot know your real key cardinality or skew, so the hot-partition warnings flag constant keys and the rates you give. Ranges built on composite string keys use
BETWEENwith a high sentinel character. -
Cost covers reads, writes and storage only — not backups, streams, global tables, DAX, data transfer or reserved capacity — and assumes provisioned capacity is sized for the peak.
Feedback is a gift. Something to improve, a feature to add, or a bug? Tell me.
Runs entirely in your browser — network requests go only to the services named on this page.