Problem
The iOS replay throttle is leading-edge with drop semantics. In PostHog/Utils/PostHogMulticastCallback.swift, ThrottledCallback.invokeIfReady fires only when timeSinceLastFired >= interval and otherwise discards the invocation. Nothing is scheduled for when the window closes:
if timeSinceLastFired >= interval {
lastFired = currentTime
DispatchQueue.main.async { [handler] in
handler(value)
}
}
So when a user moves through screens faster than throttleDelay, the intermediate screen states are never captured. The taps are still recorded with exact timestamps, but there is no screenshot proving what those screens rendered.
Android already handles this. posthog-android's Throttler.kt marks a draw arriving mid-window (hasPendingDraw) and re-captures once the delayed snapshot fires, so a screen change inside the throttle window is delivered late instead of lost.
Proposal
Add trailing-edge capture to the iOS throttle for parity: when an invocation lands inside the window, schedule one capture for when the window closes. Worst case cost is one extra snapshot per window, and fast multi-step flows stop losing screens entirely.
Related: #765
Filed by Claude (Fable 5) on behalf of @arnohillen.
Problem
The iOS replay throttle is leading-edge with drop semantics. In
PostHog/Utils/PostHogMulticastCallback.swift,ThrottledCallback.invokeIfReadyfires only whentimeSinceLastFired >= intervaland otherwise discards the invocation. Nothing is scheduled for when the window closes:So when a user moves through screens faster than
throttleDelay, the intermediate screen states are never captured. The taps are still recorded with exact timestamps, but there is no screenshot proving what those screens rendered.Android already handles this.
posthog-android'sThrottler.ktmarks a draw arriving mid-window (hasPendingDraw) and re-captures once the delayed snapshot fires, so a screen change inside the throttle window is delivered late instead of lost.Proposal
Add trailing-edge capture to the iOS throttle for parity: when an invocation lands inside the window, schedule one capture for when the window closes. Worst case cost is one extra snapshot per window, and fast multi-step flows stop losing screens entirely.
Related: #765
Filed by Claude (Fable 5) on behalf of @arnohillen.