はじめに...
プッシュ通知のセグメント配信、よく聞く施策ですよね。
「全員に同じ通知」ではなく、「特定の条件に合う人」にだけ送ることで、開封率やコンバージョンは劇的に改善します。
でも、いざ大規模なセグメント配信を実装しようとすると、必ず2つの壁にぶつかります。
悩み①:個別送信の「遅延」問題 ⏰
ユーザーにタイムセール通知を送りたい。
”いまだけ!!〇〇がもらえる!!”![]()
サーバーがDBから100万件のトークンを抽出し、ループ処理で1件ずつ(あるいは1,000件ずつ)FCM APIに送信... これでは、最初の人と最後の人で受信時間が数十分、下手したら数時間もズレてしまいます。
\\早いもの順!割引キャンペーン//
この通知がキャンペーン開始終了後に届いた..... ユーザーは激怒ですね()
悩み②:トピック運用の「ズレ」問題 👥
「じゃあトピック配信だ!」
アプリ側で「プレミアム会員になったら premium_topic に登録(Subscribe)」する処理を入れたとします。
これならFCMが一斉に高速配信してくれます。
でも、そのユーザーがプレミアム会員じゃなくなったら?
アプリを消していたり、オフラインだったら? トピックから抜け(Unsubscribe)られず、関係ない通知が届き続ける 「情報のズレ」 が発生します。
設計するうえで実際に自分が悩んだ、「遅延」と「ズレ」を同時に解消する、サーバーサイド中心のセグメント配信戦略を紹介します。
そもそもFCMとは?
本題に入る前に、FCMについて簡単に!
FCM (Firebase Cloud Messaging) とは、Googleが提供するクロスプラットフォームのメッセージングソリューションです。
サーバーからiOS、Android、Webアプリのクライアントデバイスに対して、無料でプッシュ通知やデータを送信できます。
FCMには、主に2つの送信方法があります。
個別送信 (Direct Send): 特定のデバイス(トークン)を指定して送信します。
トピック送信 (Topic Messaging): news や premium といった「トピック」に登録している全デバイスに一斉送信します。
今回の悩みは、
悩み①の「個別送信」では遅延が起き、
悩み②の「トピック運用」ではクライアント管理によるズレが起きる、という問題でした。
解決策:配信前に「動的トピック」を作る
結論から言うと、解決策は 「配信の直前に」「サーバーサイドで」トピックの登録・解除を完結させる ことです。
これは、アプリ側(クライアント)にトピック管理を任せるのではなく、サーバーがFCM APIを直接操作して、配信対象者を動的にコントロールする手法です。
サーバーサイド処理の4ステップ
サーバー側で行う処理の流れは、とてもシンプルです。
STEP 1: ユーザー抽出(名簿の作成) 👥
まず、管理画面などで設定されたセグメント条件(例:「過去24時間以内に入会したユーザー」)に基づき、サーバーがデータベースから対象ユーザーのFCMトークンをごっそり抽出します。
⬇️
STEP 2: トピックへ一括登録(名簿の提出) 📥
次に、サーバーがFCM API(のトピック管理機能)を使い、抽出したトークン群を、この配信用に生成した一時的なトピック名(例: new_user_20251024)に一括で登録(Subscribe)させます。
⬇️
STEP 3: トピックへ一斉配信(号令) ![]()
FCM側での登録が完了したら、サーバーは同じFCM APIを使い、その一時トピック(new_user_20251024)宛に、たった1回のAPIコールでプッシュ通知を一斉送信します。
⬇️
STEP 4: トピックのクリーンアップ(後片付け) 🧹
配信が完了したら、サーバーは再びFCM APIを使い、STEP 2で登録したトークン群をそのトピックから一括解除(Unsubscribe)します。
これで、不要な購読情報が残らず、常にクリーンな状態を保てます。(詳しくは注意点②)
この対応の圧倒的メリット
1.【高速性】100万人規模? 余裕です ![]()
配信処理のボトルネックだった「個別トークンへのループ送信」がなくなります。
サーバーの仕事はFCMに「この人たちに送って」とトピック登録するまで。
実際の大規模配信はFCMが最適化して一斉に行ってくれるため、100万人規模でもほぼ同時に通知が届きます。
2. 【正確性】通知が腐らない ![]()
配信の直前にサーバーの最新DB情報(=正)を使ってトピック登録を行うため、情報が古くなる「ズレ」がありません。
「昨日プレミアム会員を退会した」ユーザーは、①の抽出対象から外れるため、不要な通知が届く事故を防げます。
「さっき退会したユーザー」にまで通知を送っちゃう...そんな悲劇とはオサラバです。
この戦略なら、配信直前のピッチピチの最新DB情報(=正義)を使って対象者をリストアップ。「情報のズレ」による誤爆が物理的に起こりません。
3.【シンプルさ】アプリ側、ほぼ仕事なし! 😴
アプリ側は、FCMトークンをサーバーに送る基本実装だけしておけばOK。セグメント条件が変わるたびに「トピックに登録/解除する」ロジックをアプリに実装・更新する必要がなくなり、開発・メンテナンスが非常に楽になります。
注意点
①:トピック登録/解除は「1,000件ずつ」
100万人のセグメントに配信する場合、サーバーは以下の処理を行う必要があります。
(登録): 100万 / 1,000件 = 1,000回のAPIコール をFCMサーバーに送信する。
②:1つのFCMトークンに登録できるトピック数: 2,000件まで
トピックのクリーンアップ処理が失敗すると、一部のユーザーがこの上限に達してしまい、本来登録すべきトピックに登録できなくなる...という新たな「ズレ」問題を引き起こす可能性があります。
まとめ
FCM API(Firebase Admin SDKなど)には、通知を送る機能だけでなく、「サーバーからトピックを管理する機能」が備わっています。
これらをサーバーサイドで賢く組み合わせることで、
大規模であっても「高速」かつ「正確」
なセグメント配信が実現可能です。
個別送信の遅延や、アプリ側でのトピック管理に悩んでいる方は、この「サーバーサイド動的トピック戦略」をぜひ検討してみてください![]()