0
0

Delete article

Deleted articles cannot be recovered.

Draft of this article would be also deleted.

Are you sure you want to delete this article?

【FCM】プッシュ通知セグメント配信の「遅延」と「ズレ」、どう解決する?

Last updated at Posted at 2025-11-10

はじめに...

プッシュ通知のセグメント配信、よく聞く施策ですよね。
「全員に同じ通知」ではなく、「特定の条件に合う人」にだけ送ることで、開封率やコンバージョンは劇的に改善します。

でも、いざ大規模なセグメント配信を実装しようとすると、必ず2つの壁にぶつかります。
 
悩み①:個別送信の「遅延」問題
ユーザーにタイムセール通知を送りたい。
:point_right:”いまだけ!!〇〇がもらえる!!”:point_left:

サーバーがDBから100万件のトークンを抽出し、ループ処理で1件ずつ(あるいは1,000件ずつ)FCM APIに送信... これでは、最初の人と最後の人で受信時間が数十分、下手したら数時間もズレてしまいます。

\\早いもの順!割引キャンペーン//
この通知がキャンペーン開始終了後に届いた..... ユーザーは激怒ですね()

悩み②:トピック運用の「ズレ」問題 👥
「じゃあトピック配信だ!」
アプリ側で「プレミアム会員になったら premium_topic に登録(Subscribe)」する処理を入れたとします。
これならFCMが一斉に高速配信してくれます。
でも、そのユーザーがプレミアム会員じゃなくなったら?
アプリを消していたり、オフラインだったら? トピックから抜け(Unsubscribe)られず、関係ない通知が届き続ける 「情報のズレ」 が発生します。

設計するうえで実際に自分が悩んだ、「遅延」と「ズレ」を同時に解消する、サーバーサイド中心のセグメント配信戦略を紹介します。

そもそもFCMとは?:writing_hand:

本題に入る前に、FCMについて簡単に!
FCM (Firebase Cloud Messaging) とは、Googleが提供するクロスプラットフォームのメッセージングソリューションです。
サーバーからiOS、Android、Webアプリのクライアントデバイスに対して、無料でプッシュ通知やデータを送信できます。

FCMには、主に2つの送信方法があります。

個別送信 (Direct Send): 特定のデバイス(トークン)を指定して送信します。

トピック送信 (Topic Messaging): news や premium といった「トピック」に登録している全デバイスに一斉送信します。

今回の悩みは、
悩み①の「個別送信」では遅延が起き、
悩み②の「トピック運用」ではクライアント管理によるズレが起きる、という問題でした。

解決策:配信前に「動的トピック」を作る:muscle:

結論から言うと、解決策は 「配信の直前に」「サーバーサイドで」トピックの登録・解除を完結させる ことです。

これは、アプリ側(クライアント)にトピック管理を任せるのではなく、サーバーがFCM APIを直接操作して、配信対象者を動的にコントロールする手法です。

サーバーサイド処理の4ステップ
サーバー側で行う処理の流れは、とてもシンプルです。

STEP 1: ユーザー抽出(名簿の作成) 👥
まず、管理画面などで設定されたセグメント条件(例:「過去24時間以内に入会したユーザー」)に基づき、サーバーがデータベースから対象ユーザーのFCMトークンをごっそり抽出します。

⬇️

STEP 2: トピックへ一括登録(名簿の提出) 📥
次に、サーバーがFCM API(のトピック管理機能)を使い、抽出したトークン群を、この配信用に生成した一時的なトピック名(例: new_user_20251024)に一括で登録(Subscribe)させます。

⬇️

STEP 3: トピックへ一斉配信(号令) :spy:
FCM側での登録が完了したら、サーバーは同じFCM APIを使い、その一時トピック(new_user_20251024)宛に、たった1回のAPIコールでプッシュ通知を一斉送信します。

⬇️

STEP 4: トピックのクリーンアップ(後片付け) 🧹
配信が完了したら、サーバーは再びFCM APIを使い、STEP 2で登録したトークン群をそのトピックから一括解除(Unsubscribe)します。

これで、不要な購読情報が残らず、常にクリーンな状態を保てます。(詳しくは注意点②)

この対応の圧倒的メリット

1.【高速性】100万人規模? 余裕です :rocket:

配信処理のボトルネックだった「個別トークンへのループ送信」がなくなります。
サーバーの仕事はFCMに「この人たちに送って」とトピック登録するまで。
実際の大規模配信はFCMが最適化して一斉に行ってくれるため、100万人規模でもほぼ同時に通知が届きます。

2. 【正確性】通知が腐らない :hamburger:

配信の直前にサーバーの最新DB情報(=正)を使ってトピック登録を行うため、情報が古くなる「ズレ」がありません。
「昨日プレミアム会員を退会した」ユーザーは、①の抽出対象から外れるため、不要な通知が届く事故を防げます。

「さっき退会したユーザー」にまで通知を送っちゃう...そんな悲劇とはオサラバです。

この戦略なら、配信直前のピッチピチの最新DB情報(=正義)を使って対象者をリストアップ。「情報のズレ」による誤爆が物理的に起こりません。

3.【シンプルさ】アプリ側、ほぼ仕事なし! 😴

アプリ側は、FCMトークンをサーバーに送る基本実装だけしておけばOK。セグメント条件が変わるたびに「トピックに登録/解除する」ロジックをアプリに実装・更新する必要がなくなり、開発・メンテナンスが非常に楽になります。

注意点 :rotating_light:

①:トピック登録/解除は「1,000件ずつ
100万人のセグメントに配信する場合、サーバーは以下の処理を行う必要があります。
(登録): 100万 / 1,000件 = 1,000回のAPIコール をFCMサーバーに送信する。

②:1つのFCMトークンに登録できるトピック数: 2,000件まで
トピックのクリーンアップ処理が失敗すると、一部のユーザーがこの上限に達してしまい、本来登録すべきトピックに登録できなくなる...という新たな「ズレ」問題を引き起こす可能性があります。

まとめ

FCM API(Firebase Admin SDKなど)には、通知を送る機能だけでなく、「サーバーからトピックを管理する機能」が備わっています。

これらをサーバーサイドで賢く組み合わせることで、
大規模であっても「高速」かつ「正確」
なセグメント配信が実現可能です。
個別送信の遅延や、アプリ側でのトピック管理に悩んでいる方は、この「サーバーサイド動的トピック戦略」をぜひ検討してみてください:sunny:

参考

サーバー側からトピックを管理する

0
0
0

Register as a new user and use Qiita more conveniently

  1. You get articles that match your needs
  2. You can efficiently read back useful information
  3. You can use dark theme
What you can do with signing up
0
0

Delete article

Deleted articles cannot be recovered.

Draft of this article would be also deleted.

Are you sure you want to delete this article?