DynamoDB の制限とクォータ:実サービスに対して検証
DynamoDB の制限には 2 種類あります。API がすべてのリクエストに対して適用する固定の制約と、AWS がリクエストに応じて引き上げるデフォルトのクォータです。このページは前者を実サービスに対して実測し、後者は出典を引用します。
DynamoDB の制限には何がありますか?
アイテムは 400 KB(409,600 バイト、属性名を含む)、パーティションキーは 2,048 バイト、ソートキーは 1,024 バイトが上限です。バッチ書き込みは 25 アイテム、バッチ取得は 100 キー、トランザクションは 100 アクションかつ 4 MB までです。
テーブルはローカルセカンダリインデックスを 5 個(固定の制限)、グローバルセカンダリインデックスを 20 個(引き上げ可能なデフォルト)持てます。
- 固定か調整可能か。 アイテム、キー、バッチ、トランザクション、式、LSI の制限は固定です。スループット、テーブル数、GSI 数のクォータは、AWS がリクエストに応じて引き上げるデフォルトです。
- 実測か引用か。 最初の表のサイズと数の制限はそれぞれ、実サービスにリクエストを送って確認しました。それ以外は AWS からの引用です。
- どの制限にも回避策があり、どの制限を前提に設計すべきかにまとめています。
これらの数値をどう確定させたか
AWS はサイズの単位がバイナリ(1 KB = 1,024 バイト)だと述べているので、400 KB は 409,600 バイトを意味するはずです。プローブはそれを確認し、さらに属性名がカウントに含まれるかどうか、そして一線を越えたときにサービスが正確に何を言うかも示します。
下の最初の表にある制限それぞれについて、ドキュメントに書かれた値にちょうど乗るリクエストを組み立て、実サービスの us-east-1 に送信しました。続けて、それより 1 単位だけ超えたリクエストも送信しました。
前者は受理され、後者は拒否されるはずです。その 1 組のペアが境目を特定します。最後の列の拒否メッセージはサービス自身の文で、そのまま取得したものです。
4 行は拒否側からしか確定できませんでした。これらは CreateTable の制限で、受理側を確かめるにはインデックスを 20 個持つテーブルを作る必要があり、その数値は拒否メッセージがはっきりと述べています。確定方法の列がどれがどちらかを示しています。
検証済みの制限
| 制限 | 値 | 確定方法 | 超えたときにサービスが返す内容 |
|---|---|---|---|
| アイテムサイズの最大値 | 409,600 バイト | 409,600 は受理、409,601 は拒否 | ValidationException: Item size has exceeded the maximum allowed size |
| パーティションキー値の最大値 | 2,048 バイト | 2,048 は受理、2,049 は拒否 | ValidationException: One or more parameter values were invalid: Size of hashkey has exceeded the maximum size limit of2048 bytes |
| ソートキー値の最大値 | 1,024 バイト | 1,024 は受理、1,025 は拒否 | ValidationException: One or more parameter values were invalid: Aggregated size of all range keys has exceeded the size limit of 1024 bytes |
| 最大ネスト深度 | 32 レベル | 32 は受理、33 は拒否 | ValidationException: 1 validation error detected: Nesting Levels have exceeded supported limits: Attributes in the item have nested levels beyond supported limit |
| 式の最大長 | 4,096 バイト | 4,096 は受理、4,097 は拒否 | ValidationException: 1 validation error detected: Invalid ConditionExpression: Expression size has exceeded the maximum allowed size; |
| BatchWriteItem あたりの最大アイテム数 | 25 アイテム | 25 は受理、26 は拒否 | ValidationException: 1 validation error detected: Value '<your request>' at 'requestItems' failed to satisfy constraint: Map value must satisfy constraint: [Member must have length less than or equal to 25, Member must have length greater than or equal to 1] |
| BatchGetItem あたりの最大キー数 | 100 アイテム | 100 は受理、101 は拒否 | ValidationException: 1 validation error detected: Value at 'RequestItems.<table-name>.member.Keys' failed to satisfy constraint: Member must have length less than or equal to 100 |
| TransactWriteItems あたりの最大アクション数 | 100 アイテム | 100 は受理、101 は拒否 | ValidationException: 1 validation error detected: Value '<your request>' at 'transactItems' failed to satisfy constraint: Member must have length less than or equal to 100 |
| テーブルあたりのグローバルセカンダリインデックス数 | 20 | 拒否のみ | ValidationException: One or more parameter values were invalid: GlobalSecondaryIndex count exceeds the per-table limit of 20 |
| テーブルあたりのローカルセカンダリインデックス数 | 5 | 拒否のみ | ValidationException: One or more parameter values were invalid: Number of LocalSecondaryIndexes exceeds per-table limit of 5 |
| インデックスあたりの射影された非キー属性数 | 20 | 拒否のみ | ValidationException: 1 validation error detected: Value '<your request>' at 'globalSecondaryIndexes.1.member.projection.nonKeyAttributes' failed to satisfy constraint: Member must have length less than or equal to 20 |
| テーブルあたりの射影された非キー属性数 | 100 | 拒否のみ | ValidationException: One or more parameter values were invalid: Number of projected attributes in all indexes exceeds limit of 100, number of projected attributes:120 |
環境: Amazon DynamoDB、実サービス、us-east-1、2026-08-27 に AWS SDK for
JavaScript v3 で計測。
この表の制限は 1 つを除いてすべて固定です。テーブルあたり 20 個の GSI は、AWS がリクエストに応じて引き上げられるデフォルトのクォータです。5 個という LSI の制限は固定で、LSI はテーブル作成時にしか定義できません。
プローブが明らかにしたこと
「400 KB」は 409,600 バイトを意味し、属性名もカウントに含まれます。 ちょうど 409,600 バイトのアイテムは受理され、409,601 バイトは拒否されました。この測定はすべての属性名と値の UTF-8 長を合算しています。
これは アイテムサイズ計算ツールが実装しているのと同じ計算方法です。プローブはそのライブラリを使ってペイロードを組み立てているため、両者は主張ではなく構造によって一致しています。
この制限の背後にあるモデリングの問題には、専用のガイドがあります: DynamoDB のアイテムサイズ上限。
更新であふれた場合は別のメッセージになります。 表が引用しているのは PutItem の拒否です。アイテムを 400 KB 超に押し上げる UpdateItem は
ValidationException: Item size to update has exceeded the maximum allowed size を返します。
最初の文字列でログを検索すると、更新経路でのあふれをすべて見逃します。
インデックスあたりの射影の上限はクォータページに載っていません。 AWS のクォータページには "up to 100 attributes combined for all of a table's local and global secondary indexes" とあり、インデックスあたりの数値はありません。
実際には上限があり、それは 20 です。1 つのインデックスに 21 個の非キー属性を射影する
CreateTable は、テーブル全体の合計が 100 に近づくよりずっと前に拒否されます。
20 という数値は、API リファレンスの
Projection
ページに、配列メンバーの制約として "Maximum number of 20 items" とあるのみです。
どちらの上限も INCLUDE 射影にしか適用されません。インデックスに 20 個を超える非キー属性が必要なら、どちらの上限にもかからない ALL を射影してください。
ストレージのほうが重要なら、KEYS_ONLY を射影し、残りはベーステーブルのキーに対する
BatchGetItem で取得します。インデックスの射影を参照してください。
メッセージのうち 2 つには AWS 自身のタイプミスが含まれています。 ここでは黙って修正せず、そのまま再掲しています。maximum size limit of2048 bytes はスペースが 1 つ抜けており、number of projected attributes:120 にももう 1 つ抜けています。
これらの文字列でログを grep するなら、正しく読める文字列ではなく、サービスが実際に送ってくる文字列で grep してください。
ソートキーのメッセージは「aggregated」と言います。 文面は「Aggregated size of all range keys」です。プローブではローカルセカンダリインデックスのないテーブルを使ったので、示しているのはドキュメントどおりのルール、つまり各ソートキー値は最大 1,024 バイトまで、ということだけです。
何も発生させない 1 MB のページ
上のすべての制限は、拒否によって自らの存在を知らせます。Query と Scan のページ制限はそうしません。それを超えると、DynamoDB はエラーも警告もなく、短いページと
LastEvaluatedKey を返すだけです。
これが「Scan がテーブルの一部しか返してこない」という驚きがよくある理由であり、ページネーションが省略できない理由でもあります。また、引用できるエラーメッセージが存在しないため、誘発するのではなく測定しました:
アイテム 1 件あたり 1,000 バイトのとき、1 ページには1,029 件のアイテム(アイテムデータ 1,029,000 バイト)が収まり、LastEvaluatedKey が返されて、1,030 件目のアイテムは次のリクエストに残されました。アイテム 1 件あたり 5,000 バイトのとき、1 ページには208 件のアイテム(アイテムデータ 1,040,000 バイト)が収まり、LastEvaluatedKey が返されて、209 件目のアイテムは次のリクエストに残されました。
どちらのページもアイテムデータで 1 MiB を満たしてはいません。1 つ目は 19,576 バイト不足していました。
単純なモデルで両方のページを説明できます。ページは アイテム数 × (アイテムのバイト数 + アイテムごとのオーバーヘッド) が固定の予算に達するまで埋まる、というものです。オーバーヘッドがゼロの予算では両方の測定値に合いません。合うオーバーヘッドは 1 アイテムあたり 13 から 19 バイトの間です(整数バイトで 7 通り)。
AWS はサイズの単位をバイナリと定義しているので、その予算がちょうど 1 MiB(1,048,576 バイト)だとすると、合うのは 1 アイテムあたり 19 バイト だけで、予算は 1,048,551 から 1,048,970 バイトの間になります。
この 19 バイトは実測した定数ではなく、モデルの当てはめとして読んでください。1 MiB の予算を仮定しており、各アイテムサイズで 1 回ずつ、1 種類のキー形状で実行した結果に基づいています。2 つのページが確かに示しているのは、1 ページに収まるアイテムデータが 1 MiB 未満だということです。
コードはこれらの数値のどれにも依存すべきではありません。LastEvaluatedKey がなくなるまでページを要求し続けてください。
実測しなかったクォータ
以下の制限は AWS からの引用であり、実測ではありません。 多くはリクエストにより引き上げ可能なアカウントレベルのクォータで、到達するには時間課金のスループット、何千ものテーブル、あるいは 1 年または 3 年のリザーブドキャパシティ契約が必要です。
各行の出典はすべて AWS の Amazon DynamoDB のクォータページです。
| クォータ | デフォルト値 | 引き上げ可否 | 実測しなかった理由 |
|---|---|---|---|
| アカウント・リージョンあたりのテーブル数 | 2,500 | 可 | 2,501 個目の失敗を見るために 2,500 個のテーブルを作ると、誰かが片付ける羽目になるアカウントが残ります。 |
| テーブルあたりのプロビジョンドスループット | 40,000 RCU および 40,000 WCU | 可 | 40,000 ユニットをプロビジョンすると、1 件もリクエストを送らなくても時間単位で課金されます。 |
| アカウントあたりのプロビジョンドスループット | 80,000 RCU および 80,000 WCU | 可 | 同じ理由が 2 倍になるうえ、アカウント全体の設定を変えてしまいます。 |
| テーブルあたりのオンデマンドスループット | 40,000 RRU および 40,000 WRU | 可 | 到達するには秒間 40,000 リクエストを維持する必要があり、それは課金付きの負荷テストです。 |
| アカウントあたりのアクティブなリザーブドキャパシティ | 1,000,000 キャパシティユニット | 可 | リザーブドキャパシティは 1 年または 3 年の購入コミットメントであり、プローブではありません。 |
| テーブルサイズ | 実用上の制限なし | — | AWS は、テーブルのアイテム数とバイト数には制約がないとしています。見つけるべき境目がありません。 |
その他のドキュメント化された制限
プローブの表にすべての制限を収めることはできません。以下は AWS の制約ページ(ベクトルインデックスについてはクォータページ)からの引用で、それぞれの回避策を添えています。
| 制限 | 値 | 引き上げ可否 | 回避策 |
|---|---|---|---|
| トランザクションのサイズ | TransactWriteItems と TransactGetItems で、100 個の異なるアイテムと 4 MB のデータ | 不可 | 正しさが許す範囲で小さなトランザクションに分割する。一括ロードには BatchWriteItem を使う |
BatchWriteItem リクエスト | put または delete リクエスト 25 件、書き込むアイテム合計 16 MB(API リファレンスではリクエスト全体) | 不可 | 25 件ごとに分割し、タグの多いアイテムではシリアライズ後のリクエストサイズでも分割する |
BatchGetItem レスポンス | 100 アイテム、合計 16 MB | 不可 | レスポンスが返す UnprocessedKeys を再リクエストする |
| アイテムとその LSI エントリ | ローカルセカンダリインデックスごとに 400 KB | 不可 | LSI に射影する属性を減らす(KEYS_ONLY が最小) |
| 属性名の長さ | 64 KB。インデックスのキー名と LSI の INCLUDE で射影する名前は 255 バイト | 不可 | 名前を短く保つ。どのみちすべてのアイテムでアイテムサイズに数えられる |
| 式のプレースホルダーの長さ | #name または :value ごとに 255 バイト。1 リクエストの置換全体で 2 MB | 不可 | 短いプレースホルダー名を使う |
| 式あたりの演算子数 | 300 | 不可 | 長い OR の連鎖を複数のリクエストに分け、結果をマージする |
IN のオペランド数 | 100 | 不可 | 最大 100 値ずつの複数のリクエストを実行する |
| テーブル名とインデックス名 | 3 ~ 255 文字: A-Z、a-z、0-9、_、-、. | 不可 | 設計上の制約ではない |
| プロビジョンド → オンデマンドの切替 | テーブルごとに直近 24 時間で 4 回(オンデマンド → プロビジョンドはいつでも可) | 不可 | トラフィックのスパイクごとではなく、ワークロードごとにモードを選ぶ |
| プロビジョンドキャパシティの引き下げ | テーブルごとに UTC の 1 日あたり最大 27 回(一度に 4 回、以降 1 時間ごとに 1 回)、GSI ごとにも同様 | デフォルトのクォータ | 少ない回数で大きく引き下げる |
| シャードあたりの Streams リーダー数 | 単一リージョンのテーブルで 2。グローバルテーブルでは 1 を推奨 | 不可 | 1 つのコンシューマーからファンアウトするか、Kinesis Data Streams for DynamoDB を使う |
| テーブルあたりのベクトルインデックス数 | 5 | 可 | AWS サポート経由で引き上げをリクエストする |
スループットとパーティションの制限
次の 3 つは、負荷の下でテーブルがどう振る舞うかを決めます。いずれも AWS からの引用であり、実測ではありません。 スループットの境目を見つけるには、それを越える負荷を維持しなければならないからです。
1 パーティションあたり毎秒 3,000 読み取りユニットと 1,000 書き込みユニット。 単一のアイテムは常に 1 つのパーティションに存在し、LSI のあるテーブルではアイテムコレクション全体も同様です。
LSI がなければ、DynamoDB は忙しいパーティションキーのアイテムをソートキーで複数のパーティションに分割できます。それでも 1 つのホットなアイテムは、テーブルにどれだけのキャパシティがあってもこの数値で頭打ちになります。分割の仕組みは物理パーティションで扱っています。
回避策はキーを分散させることです。CloudWatch Contributor Insights でそのキーを見つけ、キーのサフィックスで書き込みをシャーディングし、読み取りは DAX でキャッシュします。詳しくはホットパーティションのガイドにあります。
アイテムコレクションあたり 10 GB、ローカルセカンダリインデックスを持つテーブルに限ります。 アイテムコレクションとは、1 つのパーティションキー値を共有するすべてのアイテム、つまりベーステーブルと LSI のエントリのことです。
10 GB を超えると、コレクションを成長させる書き込みは
ItemCollectionSizeLimitExceededException で拒否されます。縮小させる書き込みは引き続き成功します。
書き込みで ReturnItemCollectionMetrics: 'SIZE' を指定し、上限よりずっと手前でアラートを出してください(AWS は 8 GB を提案しています)。コレクションが際限なく成長しうるなら、LSI ではなく GSI を使います。
LSI はテーブル作成時からしか存在できないので、それは新しいテーブルとコピーを意味します。アイテムコレクションを参照してください。
オンデマンドは直前のピークの 2 倍までを吸収します。 新しいオンデマンドテーブルは毎秒 4,000 の書き込みと 12,000 の読み取りまでを維持できます。30 分以内に直前のピークの 2 倍を超えると、リクエストがスロットリングされることがあります。
既知のスパイク(ローンチ、セール)には事前ウォームを行います。UpdateTable と
WarmThroughput: {ReadUnitsPerSecond, WriteUnitsPerSecond} で、テーブルと各 GSI のウォームスループットを前もって引き上げます。
事前ウォームは課金モードを変えません。引き上げは 1 回だけ課金され、あとから下げることはできません。それ以外の場合は、少なくとも 30 分かけてトラフィックを増やしてください。それでもリクエストが拒否されたときの対処はスロットリングで扱っています。
出典: 1 パーティションあたりの数値は AWS のパーティションキーの設計、コレクションの分割はパーティションとデータ分散、アイテムコレクションの上限は LSI のページ、ランプアップはオンデマンドモードとウォームスループットのページです。
どの制限を前提に設計すべきか
これらのほとんどには一生出会いません。実際の設計を左右する一握りと、それぞれの回避策は次のとおりです:
アイテムあたり 400 KB は固定です。これに近づくアイテムは、たいてい親に埋め込まれた無制限のリストです。複数のアイテムに分割するか、大きなテキストを圧縮するか、blob を S3 に移してください。アイテムサイズ上限を参照してください。
2,048 バイトのパーティションキー、1,024 バイトのソートキー。 キーは識別子です。長い自然キーはハッシュ化し、完全な値は通常の属性として保持してください。
1 MB のページは、すべての Query と Scan を支配します。
LastEvaluatedKeyがなくなるまでループしてください。それを無視するコードは、データが 1 ページに収まらなくなった日に結果を取りこぼします。バッチ書き込みあたり 25 アイテム、バッチ取得あたり 100 アイテムは、一括ロードのループの形を決めます。分割したうえで、
UnprocessedItems/UnprocessedKeysをバックオフ付きでリトライしてください。バッチ操作を参照してください。トランザクションあたり 100 アクションと 4 MB。 正しさが許す範囲で作業を小さなトランザクションに分割し、一緒に変わる属性は 1 つのアイテムにまとめ、一括ロードには
BatchWriteItemを使ってください。トランザクションを参照してください。GSI 20 個、LSI 5 個、射影属性はインデックスあたり 20 個・テーブルあたり 100 個は、スループットのクォータよりも頻繁にアクセスパターンの設計を制約します。
INCLUDEの上限を超えるならALLを射影し、GSI を追加する前に汎用的なキー名で 1 つの GSI をオーバーロードし(シングルテーブル設計を参照)、LSI はテーブルを作成する前に決めてください。インデックスの射影と GSI と LSIを参照してください。
書き込まずに 1 件のアイテムを 400 KB のラインと照らし合わせたいなら、アイテムサイズ計算ツールがブラウザ上で動きます。すでにテーブルにあるアイテムのサイズを確認するには、DynoTable のクイックビューで開いてください。推定サイズが表示されます。
よくある質問
DynamoDB のアイテムサイズの上限はいくつですか?アイテムあたり 400 KB、正確には 409,600 バイトで、プローブで検証済みです。すべての属性名と値の UTF-8 バイト数をカウントします。これに近づくアイテムは、たいてい埋め込みリストとして保存された無制限のリレーションシップです。別々のアイテムに分割してください。
DynamoDB の単一パーティションはどれだけのスループットを処理できますか?毎秒 3,000 読み取りユニットと 1,000 書き込みユニットです。単一のアイテムは常に 1 つのパーティションに存在するので、1 つのホットなアイテムはテーブルにどれだけのキャパシティがあってもこの数値でスロットリングされます。LSI がなければ、忙しいパーティションキーのアイテムはソートキーで複数のパーティションに分割されることがあります。ホットキーは書き込みシャーディングで分散させるか、読み取りを DAX でキャッシュしてください。
DynamoDB の 10 GB の制限とは何ですか?アイテムコレクションの上限であり、ローカルセカンダリインデックスを持つテーブルにのみ存在します。1 つのパーティションキー値を共有するすべてのアイテムは、ベーステーブルとその LSI をまたいで 10 GB に収まらなければなりません。LSI のないテーブルにこの上限はありません。ReturnItemCollectionMetrics で監視し、コレクションが際限なく成長しうるなら LSI ではなく GSI を使ってください。
DynamoDB のテーブルサイズに制限はありますか?実用上はありません。AWS はテーブルのアイテム数にも総バイト数にも上限を設けていません。効いてくるのは、アイテムあたり(400 KB)、ページあたり(1 MB)、パーティションあたり(毎秒 3,000 読み取りユニットと 1,000 書き込みユニット)の制限です。
1 つの DynamoDB トランザクションにはいくつのアクションが入りますか?
100 で、データは最大 4 MB です。100 アクションの TransactWriteItems は受理され、
101 アクションのものは拒否されます。どちらも実サービスに対して検証済みです。それより大きな作業は複数のトランザクションに分割するか、一括ロードには BatchWriteItem を使ってください。