Implementing Trading Signal Subscriptions in Mobile Applications
Trading signals are time-critical. A user pays for a subscription but receives a push notification about a signal 40 seconds after its generation. By that time, the price has already moved. The entire technical challenge here is minimizing the delay from signal generation on the server to display on the screen.
Signal Delivery Architecture
FCM / APNS for signal delivery alone is an unreliable solution. Apple and Google don't guarantee push notification latency: during peak loads, delays can reach 1–5 minutes. The correct approach uses two channels in parallel:
WebSocket (primary). While the app is active (foreground) — connected to the server via WebSocket (URLSessionWebSocketTask on iOS, OkHttp WebSocket on Android). A signal arrives within 100–500 ms from generation. On connection loss — exponential backoff reconnect (1s → 2s → 4s → 8s → max 30s).
Push (fallback). When the app is in background or closed — FCM/APNS Data Message (silent push on iOS) wakes the app via BGProcessingTask or UNNotificationServiceExtension. NSE runs on each push and can display a notification with decrypted content — add the ticker, direction (BUY/SELL), entry price.
iOS caveat: UNNotificationServiceExtension has ~30 seconds to process. If contentHandler isn't called in that time — the system shows the original push. NSE shouldn't perform heavy network requests.
Subscription and Signal Access
Model: paid access via Auto-Renewable Subscription (StoreKit 2 / Play Billing Library 6+). Users without active subscriptions see signals with delay (demo mode) or don't see them at all.
Entitlement validation on the server via App Store Server Notifications V2 (APNS-signed JWT events from Apple) and Google Play Real-time Developer Notifications (Pub/Sub). Don't rely on client-side validation — the WebSocket server checks subscription_status from its own database when establishing the connection, updated via server webhooks from the stores.
Grace period: if the subscription didn't renew due to billing — don't immediately revoke access. StoreKit 2 Transaction.currentEntitlements returns a transaction with inGracePeriod status — show a banner "Payment issue, update your card" and give 3–6 days. This reduces involuntary churn.
UI: Real-time Signal Feed
Signal feed — UICollectionView with DiffableDataSource (iOS) or LazyColumn (Compose, Android). New signal inserts at the top of the list with animation without redrawing the entire list. For signals with price data — format via NumberFormatter with user locale (different markets — different price formats).
Each signal: ticker, type (BUY/SELL/CLOSE), entry price, stop-loss, take-profit, timestamp (UTC → local timezone via TimeZone.current). Colors — green/red — not only by color but also icon (accessibility: color blind users).
Signal archive with filtering — paginate via cursor (cursor-based pagination, not offset), infinite scroll via Paging 3 (Android) or custom PaginatedRepository (iOS).
Process
Design subscription scheme (pricing tiers, trial) → develop WebSocket + Push delivery → implement StoreKit 2 / Play Billing subscription → server-side entitlement validation → signal feed UI → test delivery latency → release.
Timeline Estimates
Implementing subscription + WebSocket signal feed + push fallback — 3–5 working days with ready API. If includes server architecture design (WebSocket server, Pub/Sub integration with stores) — 2–3 weeks.







