System Design Cases
DynamoDB
DynamoDB managed wide-column NoSQL by AWS — single-table design with composite (pk, sk) keys, GSI/LSI, on-demand vs provisioned capacity, Streams CDC, Global Tables active-active. Six scenarios: GetItem (single-digit ms), Query на partition с sk-range, GSI inverse lookup, PutItem→Stream→Lambda fan-out, hot-partition throttle с adaptive capacity, Global Tables LWW. Two ADRs covering single-table design vs RDBMS thinking and on-demand vs provisioned capacity.
Amazon DynamoDB: access patterns, capacity, indexes, Streams, and global consistency modes
DynamoDB is a regional key-value/document service organized around partition-key access. Base tables and local secondary indexes can serve strongly consistent reads; global secondary indexes and Streams are eventually consistent. Capacity is charged from item bytes evaluated, rounded by documented unit sizes—not from the number of attributes returned after a filter.
Global Tables now have two different modes. MREC is asynchronous multi-active replication with last-writer-wins conflict resolution and only regional transaction atomicity. MRSC synchronously replicates before success and supports strong reads across replicas, but has its own region topology, conflict, feature, and transaction restrictions.
Модель и предпосылки
- The regional endpoint routes an operation by partition key; high-cardinality keys do not by themselves prevent a single hot value.
- One strongly consistent read of an item up to 4 KiB consumes one RCU; an item larger than 4 KiB is rounded in 4 KiB units. Eventually consistent reads cost half as many units; transactional reads cost twice the strong-read units.
- On-demand instantly accommodates previously reached traffic and up to twice the previous peak; growth above that may throttle if compressed into less than the documented ramp window.
Проверяемые утверждения
- C1. Base tables and LSIs support optional strong reads; GSIs and Streams do not.
- C2. For provisioned capacity, a 6 KiB item costs two RCUs for one strongly consistent read, one RCU for an eventually consistent read, and four RCUs for a transactional read.
- C3. On-demand can instantly serve up to twice the previous peak; exceeding that inside 30 minutes can throttle unless pre-warmed or ramped.
- C4. Provisioned-to-on-demand changes are limited to four in a rolling 24 hours; on-demand-to-provisioned can occur at any time.
- C5. MREC and MRSC have different replication, read, conflict, transaction, and feature semantics.
- C6. A partition key should distribute load; high cardinality alone does not stop one disproportionately popular value from concentrating traffic.
Исполняемые сценарии
Base-table versus GSI consistency. The same logical lookup has a different consistency contract depending on the access path.
Read-capacity arithmetic. A 6 KiB item rounds to two 4 KiB units before the consistency multiplier is applied.
On-demand ramp and hot key. Scaling follows previous peak and warm throughput, while one hot key can still throttle a partition.
Streams consumer and idempotency. A committed table change enters a stream; downstream processing deduplicates retries at its own boundary.
MREC and MRSC global-table modes. MREC accepts local writes and reconciles asynchronously; MRSC synchronously replicates and rejects conflicting concurrent writes.
Ошибки проектирования
- Не делайте
Scanосновным access pattern и не рассчитывайте, что FilterExpression уменьшит уже прочитанную capacity. - Не читайте GSI с
ConsistentRead=true: strong reads там не поддерживаются. - Не считайте on-demand бесконечно мгновенным; previous peak, warm throughput и account/table quotas остаются.
- Не используйте MREC last-writer-wins для инвариантов, которым нужна согласованная read-modify-write логика через регионы.
Границы гарантии
- MRSC не является drop-in MREC: consistency mode выбирается при создании global table и не меняется для существующей таблицы.
- DynamoDB Transactions имеют документированный item/size/scope contract; внешние сервисы не входят в него.
- Streams record и Lambda event delivery имеют разные retry/deduplication boundaries; consumer обязан быть идемпотентным.