通知配信パイプライン設計(キュー・レート制御・再送)

大量の通知でも詰まらない、送信待ちの一覧を中心にした配信の組み立てと送り直しの決め方

通知配信ジョブキューレート制御リトライ死信キュー
読了時間: 10分

一気に送ると、かえって届かなくなる

人気商品が入荷すると、通知を待っていた人が一度に数百人、数千人という単位になることがあります。その全員へ同時にメールを送ろうとすると、メール配信サービス側の受付上限に引っかかったり、迷惑メール扱いされて届かなくなったりします。通知の件数が増えるほど、送る速さより「確実に届くこと」の難易度が上がるんですよね。

この記事では、通知をどういう順番で、どのくらいのペースで送るのか、失敗したものをどう扱うのかをまとめます。配信の仕組みはまだ作っていないので、実装済みの紹介ではなく、着手前に決めておきたい判断の記録です。ここは障害が起きたときの影響が広い部分なので、速さよりも、同じ結果を再現できることと、失敗から戻せることを優先して設計します。

受け付けと送信を切り離す

登録と同時に送ろうとすると起きること

「在庫が戻った」と判断したその場でメールを送る作りにすると、メール配信サービスの応答が遅れたぶんだけ、処理全体が止まります。送信先が1件なら問題になりませんが、数百件を順に処理している最中に外部サービスが重くなると、途中で時間切れになって、どこまで送れたのか分からない状態になります。

そこで、判断する処理と送る処理を切り離します。判断した側は「誰に、何を送るか」を送信待ちの一覧に書き込むところまでで終わり、実際の送信は別の処理がその一覧を順番に拾って進める。責任の範囲を分けておくのが、あとから手を入れやすい形の出発点です。

送信待ちの一覧をあいだに挟む

送信待ちの一覧は、配信の予定表にあたるものです。誰に、どの商品の連絡を、いつ送るのか。この一覧があると、通知が集中しても慌てずに済みます。並んだ分だけ順に処理していけばいいので、一度に押し寄せた通知を自分たちのペースに直せるからです。

失敗したときの扱いも一覧の上で完結します。送れなかったものは一覧に残したまま状態だけ変え、条件を満たせば後で拾い直す。送信そのものをやり直せる形にしておくと、外部サービスが一時的に不安定になっても、後から取り返せます。

送信待ちの一覧を挟んだ配信の流れ
送る相手を確定する

在庫が戻った商品と、通知を希望していた人を突き合わせる

一覧に並べる

誰に何を送るかを送信待ちの一覧に書き込む

順番に送る

ペースを調整しながら、メール配信サービスへ渡していく

結果を書き戻す

送れたか、失敗したか、送り直すかを一覧に記録する

送る処理を直接呼ばずに、一度リストへ書き出してから拾っていく。この一手間があるだけで、通知が集中しても処理が詰まりにくくなります。

いまどこまで進んだのかを状態で表す

4つの状態を決めておく

通知1件ごとに、いまどの段階にいるのかを表す状態を持たせます。決めておくのは4つで足ります。送信待ち、送信中、送信済み、失敗。この区別があるだけで、問い合わせが来たときに「その通知はどこで止まっているのか」をすぐ答えられます。

通知の一生を4つに区切っておく、というだけの表です。区切りがあると、詰まっている場所を人が見て判断できるようになります。

状態が曖昧だと、調べる手がかりがなくなる

状態を持たせずに「送った/送っていない」だけで管理すると、処理の途中で止まったものが行方不明になります。もう一度送っていいのか、すでに届いているのかが分からないので、担当者は判断できず、結果として何もできないまま放置されます。

状態をはっきり分けておけば、開発側も「どの状態のものを、どういう条件で送り直すか」を素直に書けます。あとから機能を足すときも、既存の状態の並びに沿って考えられるので、作りが崩れにくくなります。

送るペースと、失敗したときの送り直し

一度に大量に送ると届かなくなる

配信のペースには2種類の上限を用意します。ひとつは全体の上限で、1秒あたり何件まで送るかという値。もうひとつは送信先の種類ごとの上限で、同じメールサービスのアドレスに一度に集中しないよう抑えるための値です。

どちらも「速く送りきる」ためではなく「届く状態を保つ」ための設定です。同じ宛先の種類に短時間で大量に送ると、受け取る側で迷惑メールと判断されやすくなります。たくさん送ることより確実に届くことのほうが、通知としての価値は高い。この考え方を最初に共有しておくのが大事です。

送り直すべき失敗と、送り直してはいけない失敗

送信の失敗をひとまとめに扱って全部送り直すと、送り直しの処理が積み上がって一覧が詰まります。失敗の理由を2つに分けて、扱いを変えます。時間を置けば直る失敗と、何度やっても直らない失敗です。

前者は、相手側の一時的な混雑や応答の遅れ。これは少し待ってから送り直します。待つ間隔は、1回目より2回目、2回目より3回目と長くしていくのが基本です。後者は、宛先が存在しない場合など。こちらは送り直さずに失敗として確定させ、それ以上の処理を止めます。

失敗の理由ごとの扱い
時間を置けば直る失敗

混雑・応答の遅れなど 間隔を空けて送り直す

AFTER
何度やっても直らない失敗

宛先が存在しないなど 送り直さず失敗として確定

失敗の理由を2つに仕分けして、片方だけ送り直す。この線引きがないと、無駄な送り直しで一覧が埋まってしまいます。

記録の残し方を先に決めておく

送信待ちの一覧に連絡先をそのまま書かない

送信待ちの一覧には、通知の対象となる人の情報が並びます。ここにメールアドレスをそのまま書いておくと、個人情報が置かれた場所が1つ増えることになります。一覧には登録情報を指し示す番号だけを持たせ、実際の連絡先は送る直前に取り出す形にしておくと、扱いが安全になります。

動作の記録にも同じ考え方を当てはめます。調査に必要な情報だけを残し、連絡先や認証に使う値はそのまま書かない。この方針を最初に決めておくと、後から記録の書き方を直して回る作業が発生しません。

誰がいつ送り直したかを残す

通知はユーザーと直接つながる部分なので、手動の操作は必ず記録します。いつ、誰が、どの通知を送り直したのか。この履歴があると、想定外の通知が出たときに何が起きたのかを追えます。

便利な機能を増やすより、履歴が正確に残っていることのほうが、運用の安心感につながります。記録の要件は後から足すと大がかりになりやすいので、最初の仕様に含めておくのが結果的に早いです。

作り始める前に合意しておくこと

配信の仕組みに着手する前に、次の4点が決まっているかを確認します。通知1件ごとの状態の並び、送り直す条件、送るペースの上限値、失敗の分類。ここが曖昧なまま開発を始めると、運用が始まってから寄せられる要望に引きずられて、改修が続きます。

成果の数字については、いまは扱いません。通知の仕組み自体を作っていないので、通知経由の売上といった実績値は存在しないからです。まず確実に届く配信を作り、計測はそのあとで段階的に足していく。この順番のほうが、数字の意味も安定します。

まとめ

配信の仕組みは「速く送るための仕組み」ではなく「安全に送り続けるための仕組み」です。送信待ちの一覧を挟む、通知の状態を4つに分ける、失敗の理由ごとに扱いを変える、記録の残し方を先に決める。この4つを固めておけば、実装に入ってからの手戻りと、運用が始まってからのリスクを大きく減らせます。