中級読了 4 分

DynamoDB の制限とクォータ:実サービスに対して検証

DynamoDB の制限には何がありますか?

アイテムは 400 KB、パーティションキーは 2,048 バイト、ソートキーは 1,024 バイトが上限です。バッチ書き込みは 25 アイテム、バッチ取得は 100 キー、 トランザクションは 100 アクションまでです。テーブルは 20 個のグローバル セカンダリインデックスと 5 個のローカルセカンダリインデックスを持てます。 このページのこれらの数値はすべて、Amazon DynamoDB に実際にリクエストを送り、 返ってきた結果から確定させたものです。

これらの数値をどう確定させたか

AWS は根拠を示さずにクォータを公開しており、それは普段は問題になりません — ある数値が設計判断の拠り所になり、それが 400,000 バイトなのか 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 で計測。

プローブが明らかにしたこと

「400 KB」は 409,600 バイトを意味し、属性名もカウントに含まれます。 ちょうど 409,600 バイトのアイテムは受理され、409,601 バイトは拒否されました。この 測定はすべての属性名と値の UTF-8 長を合算しており、これは当方の アイテムサイズ計算ツールが実装している のと同じ計算方法です — プローブはそのライブラリを使ってペイロードを組み立てて いるため、両者は主張ではなく構造によって一致しています。この制限の背後にある より深いモデリングの問題には、専用のガイドがあります: DynamoDB のアイテムサイズ上限

誰もが引用する「射影される属性の上限」は、実は間違ったものです。 AWS の クォータページ には「テーブルのローカルおよびグローバルセカンダリインデックスすべてを合わせて 最大 100 属性」という 1 つの数値だけが記載されており、インデックスあたりの 上限には一切触れていません。実際には上限があり、それは 20 です。1 つの インデックスに 21 個の非キー属性を射影する CreateTable は、テーブル全体の 合計が 100 に近づくよりずっと前に拒否されます。20 という数値もドキュメント化 されてはいますが、それは API リファレンスの Projection ページに、配列メンバーの制約として「Maximum number of 20 items」とあるのみ です。クォータページだけを見てインデックスを設計すると、クォータページが 問題ないとしているスキーマを API が拒否することになります。両方の数値とも、 それを裏づける拒否メッセージとともに上の表にあります。

メッセージのうち 2 つには AWS 自身のタイプミスが含まれています。 ここでは 黙って修正せず、そのまま再掲しています — maximum size limit of2048 bytes はスペースが 1 つ抜けており、number of projected attributes:120 にも もう 1 つ抜けています。これらの文字列でログを grep するなら、正しく読める 文字列ではなく、サービスが実際に送ってくる文字列で grep してください。

ソートキーは合算で測定されます。 ソートキーの拒否メッセージが「the sort key」ではなく「Aggregated size of all range keys」と言っているのは、同じ 1,024 バイトの予算が、テーブルのソートキーと、そのアイテムが属するすべての ローカルセカンダリインデックスのソートキーをまとめてカバーしているからです。

何も発生させない 1 MB のページ

上のすべての制限は、拒否によって自らの存在を知らせます。Query と Scan の ページ制限はそうしません。それを超えると、DynamoDB はエラーも警告もなく、 短いページと LastEvaluatedKey を返すだけです — これが「Scan がテーブルの 一部しか返してこない」という驚きがよくある理由であり、 ページネーションが省略できない理由でもあります。

つまり引用できるエラーメッセージが存在しないため、誘発するのではなく測定 しました:

アイテム 1 件あたり 1,000 バイトのとき、1 ページには1,029 件のアイテム が収まり LastEvaluatedKey が返されました — アイテムデータ 1,029,000 バイトで、1,030 件目のアイテムは次のリクエストに残されました。アイテム 1 件あたり 5,000 バイトのとき、1 ページには208 件のアイテムが収まり LastEvaluatedKey が返されました — アイテムデータ 1,040,000 バイトで、 209 件目のアイテムは次のリクエストに残されました。

どちらのページもアイテムデータで 1 MiB を満たしてはいません — 1 つ目は 約 19,576 バイト不足していました。つまりページの予算は、アイテム自体の バイト数より多くを 1 アイテムごとに課しています。

異なる 2 つのアイテムサイズでの計測があれば、これを特定するのに十分です。 ページを アイテム数 × (アイテムのバイト数 + アイテムごとのオーバーヘッド) ≤ 予算 として扱うと、両方の計測値と整合する整数バイトのオーバーヘッドは 7 通りだけであり、そのうちちょうど 1 つだけが予算をきりのよいバイナリの メガバイトに乗せます — 1 アイテムあたり 19 バイトのオーバーヘッドで、 予算は 1,048,551 バイトから 1,048,971 バイトの間、つまり 1,048,576 を 含む範囲です。DynamoDB の「1 MB」は、自身のクォータページが述べている とおりバイナリであり、アイテムのバイト数に加えてアイテムごとのオーバー ヘッドにも使われます。1 アイテムあたりおよそ 19 バイトを見込んでおいて ください。

実測しなかったクォータ

以下の制限は AWS からの引用であり、実測ではありません。 これらは アカウントレベルのクォータで、多くはリクエストにより引き上げ可能であり、 到達するには時間課金のスループットをプロビジョンする、何千ものテーブルを 作成する、あるいは 1 年分のリザーブドキャパシティにコミットする必要が あります。そのどれもプローブではないため、プローブとしては提示していません。 各行の出典はすべて AWS の Amazon DynamoDB のクォータ ページです。

クォータデフォルト値引き上げ可否実測しなかった理由
アカウント・リージョンあたりのテーブル数2,5002,501 個目の失敗を見るために 2,500 個のテーブルを作ると、誰かが片付ける羽目になるアカウントが残ります。
テーブルあたりのプロビジョンドスループット40,000 RCU および 40,000 WCU40,000 ユニットをプロビジョンすると、1 件もリクエストを送らなくても時間単位で課金されます。
アカウントあたりのプロビジョンドスループット80,000 RCU および 80,000 WCU同じ理由が 2 倍になるうえ、アカウント全体の設定を変えてしまいます。
テーブルあたりのオンデマンドスループット40,000 RRU および 40,000 WRU到達するには秒間 40,000 リクエストを維持する必要があり、それは課金付きの負荷テストです。
アカウントあたりのアクティブなリザーブドキャパシティ1,000,000 キャパシティユニットリザーブドキャパシティは 1 年間の購入コミットメントであり、プローブではありません。
テーブルサイズ実用上の制限なしAWS は、テーブルのアイテム数とバイト数には制約がないとしています — 見つけるべき境目がありません。

どの制限を前提に設計すべきか

これらのほとんどには一生出会いません。実際の設計を左右する一握りは次の とおりです:

  • アイテムあたり 400 KB はクォータではなくモデリング上の制約です。これに 近づくアイテムは、たいてい埋め込みリストとして保存された無制限の 1 対多 リレーションシップです。 アイテムサイズ上限を参照してください。
  • 1 MB のページは、あなたが書くすべての Query と Scan を支配します。 LastEvaluatedKey を無視するコードは、データが 1 ページに収まらなく なった日に、静かに間違ったものになります。
  • バッチ書き込みあたり 25 アイテム、バッチ取得あたり 100 アイテムは、 一括ロードのループの形を決めます。 バッチ操作を参照してください。
  • トランザクションあたり 100 アクションは、DynamoDB をリレーショナルに 振る舞わせようとした人がぶつかる制限です。 トランザクションを参照してください。
  • GSI 20 個、LSI 5 個、射影属性 100 個は、スループットのクォータより はるかに頻繁にアクセスパターンの設計を制約します。しかも LSI の数は テーブル作成の瞬間に固定されます。 インデックスの射影GSI と LSIを参照してください。

上で引用した拒否メッセージのほとんどは、それぞれを引き起こすリクエストと ともに、DynamoDB のエラー配下にも専用のページを 持っています。4 つの CreateTable の拒否だけは持っていません — このページの ために取得したものだからです。

書き込まずに 1 件のアイテムを 400 KB のラインと照らし合わせたいなら、 アイテムサイズ計算ツールがブラウザ上で 動きます。自分のテーブルの中身を見たいなら、DynoTable は デスクトップ向けの DynamoDB クライアントです。

更新日