Webエンジニア向けプログラミング解説動画をYouTubeで配信中!
▶ チャンネル登録はこちら

【ITニュース解説】My webhook catcher hit 100 events and silently dropped the rest — I learned 'up to 100' is a promise with a cliff

2026年10月19日に「Dev.to」が公開したITニュース「My webhook catcher hit 100 events and silently dropped the rest — I learned 'up to 100' is a promise with a cliff」について初心者にもわかりやすく解説しています。

作成日: 更新日:

ITニュース概要

自作のWebhook受信ツールで「最大100イベント保存」と規定した際、超過分が通知なく破棄され、データ損失に気づかずバグを生んだ。エラー通知のないデータ破棄は問題。上限は常にオーバーフローイベントやAPI応答で明示し、利用者に損失を確実に伝えるべきだ。

ITニュース解説

Webhook(ウェブフック)とは、あるサービスで特定のイベント(出来事)が発生した際に、別のサービスに自動的に情報を通知する仕組みである。この通知は通常、HTTPのPOSTリクエストという形で、指定されたURLへ送られる。今回問題が発生した「Webhookキャッチャー」とは、このWebhookからの通知(イベント)を受け取り、一時的に保存しておくためのシステムのことだ。通常、開発やテストの際に、外部サービスから送られてくるイベントの内容を確認するために利用される。

記事の開発者は、統合テストのためにこのWebhookキャッチャーを構築した。そのキャッチャーは、POSTリクエストを受け取ると、そのイベントを24時間保存するHTTPSのURLを返す仕組みだった。仕様では「最大100イベントを保存する」とされており、開発者はデータを一時的に保存する領域(バッファ)として、保存できる量に限りがあり、新しいデータが来ると古いデータが上書きされていく「リングバッファ」という仕組みを実装し、特に問題はないと考えていた。

しかし、実際のテストシナリオで予期せぬ事態が発生した。外部サービスであるStripeのテストスイートが、短時間に112個ものWebhookイベントを立て続けに送信してきたのだ。例えば、サブスクリプションの作成、更新、期間延長といったイベントや、不安定なエンドポイントに接続したことによる再試行の嵐が原因で、想定よりも多くのイベントが一度に発生した。結果として、開発者が作ったキャッチャーは、仕様通り最初の100イベントだけを保存し、残りの101番目から112番目までの12イベントは、何の情報も表示されることなく、あたかも最初から存在しなかったかのように消えてしまった。

このとき、キャッチャーからはイベントが溢れたことを示すエラーメッセージも、データが途中で途切れたことを示すフラグも、何かを省略したという印も一切返されなかった。キャッチャーを利用していた別の開発者は、100個のイベントしか読み取れなかったため、Stripeからの送信は100個で終わったのだと誤解してしまった。その結果、必要なデータの一部が欠けたままの、不完全な連携機能がリリースされてしまったのである。

この問題の根本は、イベントの保存上限が100個であること自体ではなかった。本当の問題は、その上限を超えた場合にデータが「サイレントにドロップ」、つまり何の通知もなくこっそりと破棄されてしまったことにある。データがサイレントに破棄されるシステムは、非常に危険である。なぜなら、データを送信した側も、受け取った側も、データが失われたことに気づかないまま処理を進めてしまうからだ。もし、データが上限を超えた際に「HTTP 429 Too Many Requests」のようなエラーコードを返していれば、送信側は「一度に送るイベントが多すぎる」と理解し、送信を一時停止したり、後で再試行したりといった対策を取ることができたはずだ。しかし、今回は成功を示すステータスの裏でデータが隠蔽されてしまったため、誰もデータロスを検知できなかったのだ。

この深刻な問題に対し、記事の開発者は以下の3つの方法で改善を行った。

第一に、「オーバーフローを第一級イベントとして扱う」という改善だ。これは、保存できる上限数を超えてイベントが届いた場合に、その余分なイベントを単に破棄するのではなく、101番目のイベントとして、データが溢れて破棄されたことを示す特別なイベント(例えば、「タイプ:オーバーフロー、破棄された数:N」といった記録)を生成するようにしたのだ。これにより、イベントを読み取る側は、たとえすべてのイベントが取得できなくても、途中でデータが失われたことを明確に知ることができるようになった。

第二に、「読み取りAPIが『truncated: true』という情報を返す」という改善だ。キャッチャーから保存されたイベントリストを読み出すためのAPIに、イベントリストと合わせて「truncated: true」(データが途中で途切れています)というフラグを追加した。これにより、定期的にイベントをポーリング(データ取得のためにサーバーに問い合わせること)しているシステムは、わざわざ取得したイベントの数を数えて上限と比較しなくても、このフラグを見るだけでデータが一部失われたことを素早く検知できるようになり、データの欠落を見逃すリスクが減少した。

第三に、「キャッチャー作成時の応答に上限を明示する」という改善だ。Webhookキャッチャーを新しく作成した際の応答(レスポンス)に、そのキャッチャーが保存できるイベントの最大数(例:max_events: 100)を明確に含めるようにした。この変更により、キャッチャーを利用する開発者は、実際にイベントを送信し始める前に、そのキャッチャーの能力と制約を正確に把握できるようになり、後のトラブルを防ぐための適切な設計や利用計画を立てることが可能になった。

これらの改善を通して、記事の開発者が学んだ最も重要な教訓は、「最大N個まで」という表現は単なるストレージの物理的な限界を示すものではなく、システム間の「通信における契約」であるという点だ。もし開発するツールに何らかの処理上限や保存上限があるならば、その上限は常に利用者に明確に知らされるべきである。あらゆる応答やインターフェースを通じて、その上限が可視化されていなければ、それは単にリソースを制限しているのではなく、成功を装ってデータの損失を隠しているのと同じことになってしまう。

したがって、データの一時保存機能(キャッチャー、キュー、バッファなど)を構築するすべての開発者は、そのシステムが持つ上限や境界を明確に、そして「大きな声で」通知するように心がけるべきである。バッファが満杯になったとき、それは何の反応も示さないでデータを破棄する「無視」の合図ではなく、データが溢れたことを明確に伝える「シグナル」として扱われるべきなのだ。この原則を守ることで、予期せぬデータロスを防ぎ、より信頼性の高いシステムを構築できる。

関連コンテンツ

関連IT用語

関連ITニュース