Challenge
One customer, tenant or status value takes most of the traffic, so one partition throttles.
Agnotic approach
Add a shard suffix or a more specific key, and test with the real distribution of busy keys.
DynamoDB is fast when the keys match how the application reads, and slow and costly when they do not. Agnotic Technologies designs DynamoDB tables from your access patterns, then tunes keys, indexes and capacity so reads stay predictable as traffic grows.
Trusted by global innovators
























DynamoDB consulting
Amazon DynamoDB consulting is designing and tuning DynamoDB tables around the questions your application asks, not around entities. Agnotic Technologies lists every access pattern first, then chooses partition keys, sort keys, secondary indexes, capacity mode, Streams and TTL so each read is a key lookup or a query instead of a scan.
We work on new tables and on existing ones that throttle, cost more than expected or need a feature the current keys cannot serve.
If your workload needs ad hoc joins and reporting, we say so early. Analytics usually belongs in a warehouse such as Amazon Redshift, fed from DynamoDB.
Access pattern worksheet
A short version of the worksheet we fill in with your team, here for an orders and support tickets model. Every row must map to a GetItem or a Query; a row that needs a Scan sends us back to the keys.
| Access pattern | Partition key | Sort key | Index | Query it supports |
|---|---|---|---|---|
| Get an order by ID | ORDER#<orderId> | METADATA | Base table | GetItem on the full primary key |
| List a customer's orders by date | CUSTOMER#<customerId> | ORDER#<orderDate>#<orderId> | Base table, orders stored under the customer | Query with begins_with on ORDER# and a date range |
| Open tickets by status, oldest first | STATUS#OPEN#<shard> | <createdAt> | Global secondary index on status and created time | Query each shard on the index and merge by date |
| All tickets for one order | ORDER#<orderId> | TICKET#<ticketId> | Base table, tickets stored with the order | Query with begins_with on TICKET# |
| Expire abandoned carts | CART#<sessionId> | CART | TTL attribute on the item | No query: DynamoDB deletes expired items |
The shard suffix on the status key spreads one busy value across several partitions, so a single status never becomes a hot key.
Design steps
The order matters. Keys chosen before the access patterns are known are the most common cause of a rebuild.
Every read and write the application makes, with expected volume and the latency each one needs. This list drives every later choice.
A key with many distinct values that spreads traffic evenly, because each partition has its own throughput ceiling and one busy key can throttle.
Composite sort keys, such as a date plus an ID, let one Query return a filtered, ordered range instead of filtering after the read.
Global secondary indexes serve patterns that need a different key. Local secondary indexes share the partition key and are planned with the table itself.
On-demand is the AWS default and suits new or spiky traffic. Provisioned capacity with auto scaling suits steady, predictable load.
We replay realistic traffic, including your busiest customers or devices, and watch for throttling before launch.
Failure points
The problems we find most often when we review a table that is already in production.
Challenge
One customer, tenant or status value takes most of the traffic, so one partition throttles.
Agnotic approach
Add a shard suffix or a more specific key, and test with the real distribution of busy keys.
Challenge
The application uses Scan with filters for everyday reads.
Agnotic approach
Model each pattern as a Query on the table or an index, and keep Scan for exports and one-off jobs.
Challenge
A global secondary index falls behind on writes and slows the base table.
Agnotic approach
Give the index enough write capacity, or use on-demand, and project only the attributes its query needs.
Challenge
Items keep growing as lists are appended, so every read and write costs more.
Agnotic approach
Move growing lists into separate items under the same partition key and read them with a Query.
Challenge
The capacity mode was chosen at launch and never revisited.
Agnotic approach
Review usage after launch, and move between on-demand and provisioned as traffic becomes steady or spiky.
The table is only part of the system. These are the pieces we design with it.
One table when related items are read together and patterns are stable; separate tables when teams, retention rules or permissions differ. We write down why.
Stream consumers that update search indexes, publish events or feed a warehouse, written to handle retries and keep up with the stream's retention window.
Expiry timestamps for sessions, carts and temporary records, with expired items archived through Streams when you need a copy.
TransactWriteItems for all-or-nothing changes such as reserving stock and creating an order, kept small because transactional writes use more capacity.
AWS Lambda and Amazon API Gateway backends around DynamoDB, with IAM policies scoped to the tables and keys each function uses.
Encryption with AWS KMS keys, point-in-time recovery, backups and IAM conditions on partition keys for multi-tenant data.
Fit check
We would rather tell you before the build than after it.
DynamoDB works best where the main reads are known lookups by a key.
Lookups by order or customer at high volume, with transactions for the few steps that must succeed together.
Fast reads by user ID, with TTL clearing old sessions on its own.
Readings keyed by device and time, queried as recent ranges for apps and alerts.
Tenant-scoped keys with IAM conditions, so one tenant's requests cannot read another's items.
APIs on AWS Lambda where on-demand capacity follows real usage.
References
The documentation and controls behind the design choices on this page.
Limits and behaviors from the Amazon DynamoDB Developer Guide that shape the keys, indexes and pipelines we design.
Every partition in an Amazon DynamoDB table is designed to deliver up to 3,000 read units and 1,000 write units per second, so traffic concentrated on one partition key value can throttle while the rest of the table is idle.
Source: Amazon DynamoDB Developer Guide: partition key designA DynamoDB table can have up to 5 local secondary indexes, and the default quota is 20 global secondary indexes per table.
Source: Amazon DynamoDB Developer Guide: service quotasWith Time to Live enabled, DynamoDB deletes expired items within a few days of their expiration time without consuming write throughput, and AWS advises filter expressions to drop expired items from Query and Scan results until then.
Source: Amazon DynamoDB Developer Guide: Time to LiveTransactWriteItems groups up to 100 write actions into one all-or-nothing operation, and the aggregate size of the items in a transaction cannot exceed 4 MB.
Source: Amazon DynamoDB Developer Guide: transactionsDynamoDB Streams records a time-ordered sequence of item-level changes and keeps it for up to 24 hours, so stream consumers must keep up or lose older records.
Source: Amazon DynamoDB Developer Guide: DynamoDB StreamsScope and cost
We do not publish prices. These are the factors we size on the scoping call.
How many patterns the application has and how many entity types share a table.
A new design is a worksheet and a schema; an existing table adds a backfill and a switch-over.
Moving data from a relational database means mapping rows to items and checking counts after the load.
Search, events, analytics feeds and archives each add a consumer to build and monitor.
Tenant keys, IAM conditions and tests that prove one tenant cannot read another's data.
How realistic the traffic replay must be, including your busiest keys.