著者: Dmitriy · · 10 分で読めます

新規 DynamoDB テーブルは書き込み毎秒何件でスロットリングする?

新規の DynamoDB テーブルは、毎秒 4,000 回の書き込みを受け付けます。私たちはそこに毎秒 8,000 回を提供しました。テーブルが処理したのは毎秒 4,000 回で、これは AWS がドキュメントに記載している数値です。残りは HTTP 400 で拒否されました。

追加のキャパシティは、こちらが何もしなくても届きましたが、遅れて届きました。最初のステップである毎秒 5,000 回への上昇は、実行開始から 8.6 分後でした。ローンチ当日に毎秒 4,000 回を超える書き込みが必要なら、トラフィックが来る前にウォームスループットを設定してください。

計測は 2026 年 8 月 27 日と 28 日に us-east-1 で、実行ごとに新規テーブルを 1 つ使い、約 1 KB のアイテムとランダムなキーで行いました。10 秒間のバーストについては、9 月に 1 回再計測しています。

多くの記事が引用する公開計測は 2019 年のものです。

新規テーブルは 10 秒間のバーストの後、毎秒 4,000 回の書き込みにとどまる

負荷生成器は一定のレートで 30 秒間書き込みを送り、その後レートを引き上げました。このレートを「提供」と呼びます。「達成」は DynamoDB が受け付けた数で、リクエストを 1 件ずつ数え、ウィンドウ全体で平均したものです。

提供達成(30 秒間の平均)スロットリングされたリクエスト
1,000/s1,000/s0
2,000/s2,000/s0
3,000/s3,000/s0
4,000/s4,000/s0
5,000/s4,132/s25,992
6,000/s4,131/s55,966
8,000/s4,134/s115,922

毎秒 4,000 回までの書き込みはすべて通りました。それを超えると、何回提供しても 30 秒間の平均は 4,131~4,134 にとどまりました。DynamoDB は、毎秒 5,000 回ではリクエストの 17% を、8,000 回では 48% を拒否しました。

これらの平均が 4,000 を上回るのは、各ステップが最初にバーストで始まったためです。9 月に 10 秒単位で再計測したところ、スロットリングが発生した各ステップは最初の 10 秒間が毎秒 4,400~4,480 回で、その後は 4,000 回でした。

10 秒間の 4,400 と 20 秒間の 4,000 を平均すると約 4,133 になり、8 月のウィンドウと一致します。新規テーブルが処理し続けるレートは、ドキュメントどおりの 4,000 です。

そのバーストは小さなものでした。4,000 を 400~480 上回る状態が 10 秒間続くと、合計で 4,000~4,800 の追加書き込みユニットになります。

8 月のテーブルは、5,000 のステップの前に毎秒 1,000~4,000 回の書き込みで 120 秒間動いていました。これにより、4,000 を下回る未使用分が少なくとも 180,000 ユニット残っていました。さらに、ランナーはウィンドウ間で 2 秒間休止していました。

AWS はバーストキャパシティをドキュメントに記載しており、これはスパイクに備えて最大 300 秒分の未使用キャパシティを保持します。私たちが観測したバーストは、それが許す量よりはるかに小さいものでした。理由はわかりません。

スロットリングは HTTP 400 で、存在しないホットキーを疑わせる

上限で DynamoDB が書き込みを拒否すると、エラーは次のようになります:

ThrottlingException: Throughput exceeds the current capacity of your table or index. DynamoDB is automatically scaling your table or index so please try again shortly. If exceptions persist, check if you have a hot key: https://docs.aws.amazon.com/amazondynamodb/latest/developerguide/bp-partition-key-design.html

ステータスコードは 5xx ではなく 400 です。5xx だけをリトライするクライアントは、これらの書き込みを失います。5xx だけを監視するアラームは、書き込みの半分が失敗している間も緑色のままです。

最初の拒否は、5,000 のウィンドウでは開始から 3.8 秒後、6,000 では 1.9 秒後、8,000 では 0.9 秒後に来ました。

キーはランダムな UUID だったので、ホットなキーは 1 つもありませんでした。現在 AWS はスロットリングエラーに ThrottlingReasons フィールドを付与しており、発動した上限の名前がわかります。私たちはそれを記録していません。

最大値を設定していないオンデマンドテーブルについて、AWS は 2 つの理由を挙げています。パーティションごとの上限と、テーブルごとのアカウントレベルのクォータです。私たちの 4,000 はそのクォータのデフォルト値 40,000 をはるかに下回るので、発動したのはおそらくパーティションごとの上限です。

計時したのは DynamoDB が受け付けたリクエストだけです。8,000 のウィンドウでは、8 台のランナーのうち 7 台でその中央値は 4~5 ms のままでした。8 台目はインフライトのリクエスト数の上限に達し、中央値は 78 ms、p99 は 1,327 ms に上がりました。

追加のキャパシティは 8.6 分後に届き、8,000 には届かなかった

AWS のオンデマンドのページには、新規テーブルは "able to sustain up to 4,000 writes per second and 12,000 reads per second." とあります。

同じページには、オンデマンドは "instantly accommodates up to double the previous peak traffic on a table." とも書かれています。2 倍を超える増加については、"throttling can occur if you exceed double your previous peak within 30 minutes." と警告しています。

伸び方を観察するため、別の新規テーブルに毎秒 8,000 回の書き込みを提供し続けました。各ランナー Lambda のタイムアウトは 10 分だったので、負荷は 8 分間のウェーブ 4 回として実行し、ウェーブ間の休止は 32~39 秒でした。

受け付けられた書き込みを 10 秒単位で数えました。経過分数は最初のウェーブの開始から数えます:

ウェーブ経過分数毎秒の処理数
10–8.0約 4,000
2–38.6–24.2約 5,000
324.2–25.2約 6,000
425.8–33.8約 7,000
8,000/s 提供時の 1 分ごとの達成書き込み数/秒(8 分間のウェーブ 4 回)

テーブルは最初のウェーブの間ずっと毎秒 4,000 回を処理しました。ウェーブ 2 の開始時に 5,000、ウェーブ 3 の終盤に 6,000、ウェーブ 4 の開始時に 7,000 に達しました。提供した 8,000 を処理することは一度もありませんでした。

最初のウェーブは、トラフィックのない状態から一気に 8,000 まで上げました。AWS は事前のウォームアップか、少なくとも 30 分かけて増加を分散させることを勧めており、そうしないとスロットリングが起きると警告しています。最初のウェーブはその警告に当てはまります。

その後については、2 倍の条項はもっと速い上昇を予測します。4,000 で 8 分間動いた後の 8,000 は、そのピークのちょうど 2 倍で、それを超えてはいません。5,000 で約 15 分間動いた後の 2 倍は 10,000 で、私たちが送った量を上回ります。

それでも、4 つのウェーブすべての、どの 10 秒単位のバケットにもスロットリングがありました。AWS は、トラフィックがどれだけ続けば直前のピークとして数えられるのかを定義していません。そのため、2 倍の条項がなぜ成り立たなかったのかはわかりません。

3 回のステップのうち 2 回は、アイドルの休止の直後、ウェーブの開始時に来ました。最初の 3 つのウェーブは、それぞれバーストのバケットで始まってもいます。毎秒 4,223、5,293、5,293 回の書き込みです。テーブルを動かしたのが負荷下の時間なのか休止なのかは判別できません。

これは 1 回の実行であり、この形が繰り返されることはまだ示していません。2019 年のテストは、9,000 の提供に対してテーブルが毎秒約 7,000 回の書き込みに達した状態で終わりました。私たちのテストは、8,000 の提供に対して 7,000 で終わりました。

初日から 4,000 を超える書き込みを受けるには、先にウォームスループットを設定する

AWS はウォームスループットを、テーブルが "can instantaneously support" 読み取りと書き込みと定義しています。新規のオンデマンドテーブルは、毎秒 4,000 書き込みユニットと 12,000 読み取りユニットを報告します。

これらの値はイベントの前に引き上げられ、AWS はこれを事前ウォームアップと呼んでいます。テーブルの課金モードは変わりません。引き上げた値を再び下げることはできません。

# Raise an existing table's write warm throughput to 10,000/s
aws dynamodb update-table --table-name Orders \
  --warm-throughput WriteUnitsPerSecond=10000

# Status reads UPDATING, then ACTIVE when the new value is set
aws dynamodb describe-table --table-name Orders \
  --query 'Table.WarmThroughput'

create-table も同じ --warm-throughput フラグを受け付けるので、新規テーブルを最初からウォームな状態で始められます。更新はバックグラウンドで実行され、AWS によると所要時間は値とテーブルのサイズによって変わります。イベントのかなり前に開始してください。

各グローバルセカンダリインデックスは独自のウォームスループットを持ちます。インデックスが自分への更新を吸収できないと、DynamoDB はベーステーブルへの書き込みをスロットリングします。したがって、インデックスもウォームアップしてください:

aws dynamodb update-table --table-name Orders \
  --global-secondary-index-updates \
  '[{"Update":{"IndexName":"ByCustomer","WarmThroughput":{"WriteUnitsPerSecond":10000}}}]'

事前ウォームアップには 1 回限りの料金がかかります。増加 1 ユニットごとに、リージョンの時間単価で書き込みキャパシティユニット 1 つ分です。us-east-1 で書き込みを 4,000 から 10,000 に引き上げると、6,000 × $0.00065 で $3.90 です。

最大スループットは、オンデマンドの別の設定です。AWS はそれを超えるリクエストをベストエフォートでスロットリングし、バーストキャパシティが一時的にそれを超えることもあります。これはテーブルを事前にウォームアップするものではありません。

ウォームスループットは書き込みユニットで数えます。1 ユニットは最大 1 KB の書き込みに相当するので、3 KB のアイテムは 3 ユニットを使います。テーブルがどれだけウォームでも、1 つのパーティションキーが受けられるのは毎秒最大 1,000 ユニットです。

新規テーブルのピーク書き込みユニット/秒対処
4,000 まで書き込みが多数のパーティションキーに分散していれば、何もしなくてよい。
4,000 超、日付が決まっている事前にウォームスループットを引き上げ、ACTIVE になるまで待つ。
4,000 超、予告なしSDK のリトライをオンのままにし、5xx ではなくスロットリングされたリクエストでアラームを上げる。

読み取りは、フリートが限界に達するまでスロットリングされなかった

別の新規テーブルに 1,000 件のアイテムを投入し、 GetItem 呼び出しで読み取りました。約 1 KB の読み取りは 1 回あたり 0.5 読み取りユニットです。

最も高いレートでも、DynamoDB は送ったすべての読み取りを受け付けました。平均で毎秒 12,762 回、スロットリングはゼロです。8 台のランナーのうち 5 台が、先に自分自身の上限に達しました。

これは毎秒約 6,400 読み取りユニットで、ドキュメントに書かれた 12,000 読み取りユニットのおよそ半分です。読み取りの上限は見つけられませんでした。

ラップトップは自分の経路を計測し、Lambda 1 つは自分自身を計測する

最初の負荷生成器は、マドリードのラップトップ上で動く Node スクリプトでした。us-east-1 への各リクエストは、中央値で 130~144 ms かかりました。

スクリプトは毎秒 1,000 回の書き込みをペーシングできました。2,000 回を求めると、インフライトのリクエストが 1,500 件ある状態で毎秒 107 回しか送れませんでした。DynamoDB はそのどれもスロットリングせず、58 件は別のエラーで失敗しました。限界は私たちのクライアントと、バージニアまでの経路でした。

次に、同じループを us-east-1 の Lambda 関数 1 つで、3,008 MB のメモリを割り当てて実行しました。これは中央値 10 ms で毎秒 2,000 回の書き込みをペーシングできました。

4,000~8,000 の提供に対しては毎秒 1,020~1,096 回しか送れず、インフライトのリクエスト 600 件という上限に張り付きました。DynamoDB はそれらもまったくスロットリングしませんでした。

CPU は記録しておらず、試したメモリサイズも 1 つだけです。わかっているのは、このサイズのランナー 1 つでは毎秒 2,000 回の書き込みを大きく超えてペーシングできない、ということだけです。

最終的な計測器は、そうした関数 8 つです。それぞれが提供レートの 8 分の 1 をペーシングし、全員が 20 秒先の共通の時刻に開始します。結果は数えたリクエストの合計です。

各ランナーは、インフライト上限に達したときにもそれを報告します。書き込みテストでは、8,000 のウィンドウで 1 台が上限に達しました。読み取りテストでは、最も高いレートで 5 台が達しました。

持続テストでは、8 台のランナーがそれぞれ 4 つのウェーブを実行しました。その 32 回の実行のうち 25 回で、ランナーが上限に達しました。

1 回が成功するまでに 3 回の実行が失敗した

ラップトップ上のドライバーは、最初は AWS CLI を通じて各ランナーを同期的に呼び出していました。この方法では、実行の間ずっと HTTPS 接続を 1 本、無通信のまま開いておくことになります。おそらく自宅のルーターが、それほど長くアイドルだった接続を切断したのです。

メモには、この形で壊れた実行が 3 回記録されています。そのうち 1 回では、あるランナーが決して完了しないリクエストで固まりました。CLI はタイムアウトし、自分で呼び出しをリトライしました。再実行されたランナーは、予定された開始時刻がとうに過ぎているのを見つけました。

メモには 700 秒と 900 秒での CLI の読み取りタイムアウトも記録されていますが、それ以外の点ではメモ同士が食い違っています。あるメモは関数が完了していたと書いています。別のメモは、あるランナーが関数のタイムアウトまで固まり、診断情報を何も残さなかったと書いています。

うまくいったバージョンは、次の 6 つのルールに従っています:

  • 非同期で呼び出し、結果は帯域外で届ける。 呼び出しはすぐに戻ります。各ランナーは結果を小さな DynamoDB テーブルに書き込み、ドライバーは 8 行が揃うまでポーリングします。
  • すべての層でリトライをオフにする。 計測クライアントはリクエストごとに 1 回だけ試行します。リトライは、私たちが数えているスロットリングを隠してしまうからです。
  • 上流でも何もリトライしない。 CLI と非同期呼び出しは 1 回だけ試行します。ほぼすべての場合、重複した実行は開始時刻がすでに過ぎていることに気づくので、はっきりと失敗します。
  • すべてのリクエストにタイムアウトを設定する。 私たちのタイムアウトは 8 秒です。
  • ウォッチドッグを追加する。 予定より 1 分過ぎると、ランナーは部分的なカウントと、どこで止まっていたかのメモを返します。
  • 支出に上限を設け、後片付けをする。 各ランナーは決まった操作数を超えると中断し、finally ブロックで実行が作成したものをすべて削除します。

1 リージョンで実行ごとにテーブル 1 つという計測には、未解決の疑問が残る

  • 各数値は 1 つの新規テーブルを、2026 年 8 月 27 日または 28 日に us-east-1 で 1 回計測したものに、10 秒間のバーストを確かめた 9 月の再計測 1 回を加えたものです。どれも分布ではありません。
  • 送ったのは約 1 KB の単一アイテムの PutItem と結果整合性のある GetItem 呼び出しで、キーはランダム、インデックスやストリームはありません。BatchWriteItem は、スロットリングされたアイテムをエラーではなく UnprocessedItems として返すことがあります。
  • すべての書き込みは新しいキーを挿入しました。同じアイテムへの更新はテストしていません。
  • リトライはオフでした。AWS SDK はデフォルトでスロットリングエラーをリトライするので、アプリケーションからはエラーより先に書き込みの遅延が見えます。
  • 読み取りの上限は見つけられませんでした。
  • すべてのカウントはクライアント側のものです。成長のステップと 10 秒間のバーストは私たちが観測した形であって、計測した原因ではありません。
  • 以下のコストは定価です。

クラウドサービスを自分で計測するなら応用できること

  • 負荷生成器はターゲットと同じリージョンに置くこと。そうしないと、経路を計測することになります。
  • 負荷を複数のランナーに分割し、各ランナーが飽和した時点を記録し、数えたリクエストを合計すること。
  • ウィンドウより細かい単位でバケット化すること。私たちの 30 秒間の平均は、10 秒間のバーストを隠していました。
  • 先に実行のコストを見積もること。us-east-1 の定価で、受け付けられたリクエストのコストは上限計測の実行で約 $0.49、持続負荷の実行で $6.33 でした。Lambda、失敗した実行、事前の探りは別途かかります。

オンデマンドスループットのリファレンスには、1 分ごとの成長データを含め、これらの実行で得たすべての表があります。DynamoDB のスロットリングでは、その 400 のほかの原因を扱っています。

DynoTable はテーブルをオンデマンドとプロビジョンドキャパシティの間で切り替えられます。ウォームスループットは AWS コンソールか CLI で設定します。自分のテーブルで試すには DynoTable をダウンロードしてください。

Console なしで DynamoDB を扱う

DynamoDB では実行できない本物の SQL(JOINs、GROUP BY、集計)を実行する高速な DynamoDB デスクトップクライアント。ビジュアル編集と、あなた自身の Bedrock キーで動く AI エージェントを備えています。

30日間無料トライアル、クレジットカード不要 — その後は期限のない Free プラン。