アーキテクチャ2026年8月3日8 分で読めます

Webhook とポーリングの違い:流行ではなく壊れ方で選ぶ

ポーリングはリクエストを無駄にしますが、穏やかに劣化します。Webhook は効率的でも、黙って失敗します。本格的な連携の多くが行き着くハイブリッド構成も紹介します。

ポーリング · 欠落は自然に埋まる自前のループ3 時間ダウン次のポーリングsince=cursor最新まで取得復旧のために書き足すコードはないWebhook · 欠落が見えないプロバイダー500s 3 時間リトライ後、打ち切り何もないエラーもカーソルもないどこにも兆候なしデータがないことと、何も起きていないことの区別がつかない
大事な比較は、1 時間あたりのリクエスト数ではない。壊れたときに、それぞれの方式が何を残すかだ。

よくある語られ方では、ポーリングは素朴なやり方で、Webhook はそこから卒業した先にあるものです。わかりやすい話ですが、これがチームを誤ったアーキテクチャに導くことは意外なほど多くあります。

役に立つ問いは、どちらが効率的かではありません。効率なら Webhook が上で、比べるまでもありません。役に立つ問いは、壊れたときにそれぞれがどうなるかです。午前3時に付き合うことになるのはその性質で、しかも両者はほぼ正反対だからです。

TL;DR

  • ポーリングは目に見える形で、回復できる形で失敗します:失敗に気づけますし、次のポーリングで追いつきます
  • Webhook は音もなく、取り返しのつかない形で失敗します:エラーは何も出ず、イベントはただ消えます
  • Webhook では、ポーリングならタダで手に入る仕組みを自分で作ることになります:リトライ、重複排除、順序制御、署名検証
  • 本番環境の連携の多くは、最終的にハイブリッドになります:レイテンシーは Webhook が、正確さは照合用のポーリングが担います
  • どちらか 1 つしか作れず、レイテンシーより正確さが大事なら、ポーリングです

よく示される比較

ポーリングWebhook
レイテンシーポーリング間隔。平均するとその半分ほぼリアルタイム
無駄なリクエストほとんどが無駄なし
コストを負担する側自分送信元
公開エンドポイント不要必要
順序自分で制御できる保証されない
セットアップHTTP 呼び出しとループエンドポイント、TLS、署名検証、重複排除、リトライ

この表を見ると、たいていの人が重視する行では Webhook が勝っています。だからこそ多くのチームが乗り換えて本番に出し、その後 2 か月間、気づかないままイベントを失い続けるのです。

本当に決め手になる比較

代わりに、こう問いかけてください:これが壊れたとき、自分はどうやってそれを知るのか。

ポーリングは、劣化するときにそれ自体が知らせてくれます。サーバーがダウンしていれば、ループは動きません。復帰すると、次のポーリングが「前回のカーソル以降に何が変わったか」を尋ね、すべてを受け取ります。復旧は自動で、すでに書いたコード以外は何も要りません。API がダウンしていれば、ポーリングは 500 を返し、自分のエラー率にすぐ表れます。プル型では、最後に正常だった自分の位置を常に把握しています。この 1 つの性質には、とてつもなく大きな価値があります。

Webhook は、自分の側からは見えない形で失敗します。まずいデプロイのせいで、エンドポイントが 6 時間 500 を返し続けたとします。プロバイダーはリトライし、あきらめ、次へ進みます。ログには何も異常が出ません。受け取っていないリクエストはログに残せないからです。カーソルも、欠落の検知も、「400 件遅れている」という数字も、システムのどこにもありません。データがないことと、動きがないことは見た目がまったく同じです。静かな日曜日には、両者を区別できません。

ポーリング · 欠落は自然に埋まる自前のループ3 時間ダウン次のポーリングsince=cursor最新まで取得復旧のために書き足すコードはないWebhook · 欠落が見えないプロバイダー500s 3 時間リトライ後、打ち切り何もないエラーもカーソルもないどこにも兆候なしデータがないことと、何も起きていないことの区別がつかない

決め手はこの非対称性です。ポーリングの最悪のケースは、いずれ追いつく古いデータです。Webhook の最悪のケースは、欠けていることに永遠に気づかないデータです。

二次的なコストもここから生じます。Webhook を使うと、リトライのロジックを自分で持つことになります。プロバイダーのリトライ期間には限りがあり、寛大なプロバイダーでも 3 日であきらめるからです。冪等性も自分で持ちます。少なくとも 1 回の配信(at-least-once)では、重複は必ず起きるからです。順序のガードも自分で持ちます。リトライによって、イベント #2 がイベント #1 を追い越すからです。署名検証も自分で持ちます。エンドポイントは公開されていて、誰でも POST できるからです。そして、常に稼働している公開 HTTPS エンドポイントも自分で持つことになります。これは「アプリはたいてい動いている」とは別の可用性要件です。

どれも、単独なら難しくありません。しかし全部合わさると、「Webhook を使えばいい」が 2 週間のプロジェクトになり、終わったと思った時点ではまだ終わっていない、ということになります。

ポーリングが本当に正解になるとき

次のような場合は、効率の議論に流されないでください。

わかりやすいのは、レイテンシーが要らない場合です。夜間の会計データの同期、在庫の照合、CRM のデータ拡充ジョブ:5 分の遅れに誰も気づかないなら、誰にとっても価値のない性質のために、本物の複雑さを支払っていることになります。

次に、受け取る場所がない場合です。デスクトップアプリ、VPN の内側の社内ツール、誰かのノート PC で動くジョブ。Webhook をトンネルで localhost に通すのは開発のテクニックであって、本番のアーキテクチャではありません。その境界がどこにあるかは「ngrok だけでは足りない理由」に書きました。

チームがいちばん判断を誤りやすいのは、レイテンシーより正確さが大事で、締め切りが 1 週間後に迫っているときです。中身を理解できるカーソル方式のポーリングは、半分しか完成していない Webhook パイプラインに勝ります。

量が少ない場合も同じ結論になります。5 分ごとのポーリングは 1 日 288 回のリクエストで、どんなレート制限にも引っかかりません。運用のシンプルさもタダで付いてきます。プロバイダー自身の Webhook が不安定な場合もそうです:配信が当てにならず、イベントログも貧弱なら、その送信を信じるより、API をポーリングするほうが信頼できます。

Webhook が複雑さに見合うとき

Webhook が元を取るのは、人が待っているときです。決済の確認、デプロイの状況、チャットのメッセージ。1 秒を切る速さが意味を持ち、ポーリングでそれをまねようとすると、API を叩き続けることになります。

イベントがまれで予測できない場合も Webhook が勝ちます。1 日 2 回しか起きないことをポーリングすると、リクエストのおよそ 99.9% は空振りです。Webhook はまさにこのために設計されました。反対の極端では、量のせいでポーリングがそもそも成り立たなくなります:10,000 店舗がそれぞれ 30 秒の鮮度を必要とすると、1 日 28,800,000 件のリクエストになります。そこに届くずっと前に、レート制限に引っかかります。

最後は、長時間かかるジョブです。動画のトランスコード、モデルの推論、バッチでのエクスポート。いつ終わるかを知っているのはプロバイダーで、こちらは推測するしかありません。AI やメディアの API が Webhook を強く推すのはそのためです。AI エージェント向けの Webhook の記事も参照してください。

ハイブリッド構成:どのみち作ることになるもの

成熟した連携のほぼすべてが、最終的にここにたどり着きます。インシデントの後でたどり着くより、意図してたどり着くほうが安上がりです。レイテンシーは Webhook が担い、正確さは定期的な照合用のポーリングが担います。

// Fast path: webhook, near-real-time
export async function POST(req: Request) {
  const event = await verify(req);
  await upsertEvent(event);           // idempotent by provider event id
  return new Response(null, { status: 200 });
}

// Safety net: every 15 minutes, ask what we should have
async function reconcile() {
  const now = new Date();             // before listing, so nothing updated mid-sweep is skipped
  const since = await getLastReconciledAt();
  for await (const obj of provider.list({ updated_since: since })) {
    await upsertEvent(obj);           // same idempotent path, no-op if webhook won
  }
  await setLastReconciledAt(now);
}

照合ジョブに必要なのは定期実行の関数だけで、すでに書いたコードをそのまま使えます。その代わりに、Webhook の最悪の性質である「音もなく永久に失われる」を、「最大 15 分遅れる」に変えてくれます。これはまったく別の種類のリスクです。最悪のケースは決済の取りこぼしですらありません。それならいずれ誰かが気づきます。最悪なのは access.revoked の取りこぼしで、こちらは誰も気づきません。

これが機能する条件は、両方の経路が同じ冪等な書き込み処理を通ることです。Webhook がすでに処理していれば、照合は何もしません。処理していなければ、照合が直します。これが成り立つのは、自分側の到着時刻ではなく、プロバイダーのイベント ID で重複排除している場合だけです。実装パターンは同じ Webhook を 2 回受け取ったときの記事にあります。

そのうえで、重なりを計測します。Webhook が取りこぼしたものを照合が見つけた回数を数えてください。その数が Webhook パイプラインの本当の損失率で、それを正直に測る方法はほかにありません。1 か月間ゼロなら、Webhook は健全です。急に増えたら、それがなければ決して気づかなかった障害が起きています。

忘れられがちな中間の選択肢

ポーリングが愚直である必要はありません。

カーソル方式のポーリング、つまり「すべて取得して差分を取る」のではなく ?since=<cursor> を使う方法は、はるかに安く済み、項目を飛ばすこともありません。カーソルは処理に成功したときにしか進まないからです。

条件付きリクエスト(ETag を使った If-None-Match、または If-Modified-Since)は、ボディなしの 304 を返します。多くのプロバイダーは、これをレート制限に数えません。わずかなコストで、積極的にポーリングできます。

ロングポーリングなら、Webhook 並みのレイテンシーとプル型の回復力を両立できます。提供されていることは少ないものの、提供されていれば、両方のいいとこ取りになることが多いです。

一定間隔ですべてを取得するコストを理由にポーリングを退けていたなら、いちばん出来の悪いポーリングと比べていたのかもしれません。

AnyHook の位置づけ

Webhook が黙って失敗するのは、届くはずだったものの記録を誰も持っていないからです。AnyHook がその記録になります。

プロバイダーは in.anyhook.net/you/app に POST します。すべてのイベントは配信を試みる前に永続化されるので、次のようになります:

  • 欠落が見えるようになります。配信の失敗は数えられ、表示され、1 回、5 回、20 回連続の失敗で通知されます。もう「音もなく」とは言えません
  • 復旧は照合ジョブではなく再送になります。サーバーがダウンしていた期間を選び、ログから配信し直します。失敗したイベントの再送は月間クォータにカウントされません。ただし 1 日の再送上限があり、コンピュート枠を消費します
  • インフラの手間は、AnyHook が一度だけ引き受けます:指数バックオフ付きのリトライ、永続的なログ、そしてプロバイダーごとの検証方式の代わりに 1 つの AnyHook-Signature ヘッダー

それでも、照合用のポーリングが要らなくなるわけではありません。プロバイダーがそもそもイベントを送っていなければ、どんな中継サービスもそれを生み出せません。ただ、障害の形は「音もなく、取り返しがつかない」から「記録され、通知され、再送できる」に縮まります。ハイブリッド構成で得ていたものの大半はこれです。

何かに登録する前に試すなら、アカウントなしで、コマンド 1 つで実際に使える受信 URL が返ってきます:

curl -X POST https://anyhook.net/api/v1/quickstart

レスポンスには、プロバイダーに設定する inbound_url、API 経由でイベントログを読むための api_key、そして claim_url が含まれます。このエンドポイントは一時的なものです:紐付け用の URL を開いてログインし、アカウントに紐付けない限り、エンドポイントとそのイベントは 7 日後に削除されます。紐付ければ同じ URL をそのまま使えます。

まとめ

壊れ方で選んでください。ポーリングは遅れますが、自然に回復します。Webhook は速いものの、黙って取りこぼします。レイテンシーが人にもレート制限にも影響しないなら、ポーリングは初心者向けの選択肢ではなく、最悪のケースがよりましな選択肢です。そして本番環境で Webhook を使うなら、必要になる前に照合用のポーリングを加えてください。実際に何件のイベントを失っているかを知る方法は、それが生む指標しかないからです。

すべての記事2026年8月3日 · 8 分

Webhook を、もう取りこぼさない。

URL を 1 つ変えるだけで、リトライ、イベントログ、1 クリックでの再送が使えます。先に動きを見ることもできます。新規登録して 30 秒の障害訓練を実行すると、サーバーがダウンしていてもイベントが失われない様子を確認できます。サーバーを用意する必要はありません。