Scheduled delivery activating late
Alert: KrabkaDeliveryActivationLate,
histogram_quantile(0.99, sum by (le, instance) (rate(krabka_broker_delivery_activation_lateness_seconds_bucket[5m]))) > 1
for 10m.
What it means
KFC-1 scheduled delivery holds a batch invisible until its activation time,
then makes it visible. delivery_activation_lateness_seconds is how far past
that deadline the batch actually became visible. A healthy broker reports
zero.
A rising tail says one of two things, in the metric’s own words: the bound the
broker publishes is not honest, or the scheduler is starved of CPU. Both matter
because the bound is a promise to consumers. A partition with
delivery.mode=scheduled is telling its readers that a record does not appear
before its time and does appear at it; lateness is the second half of that
breaking while the first half still holds.
Nothing errors. The records arrive, late, and only this series says so.
Confirm
histogram_quantile(0.99, sum by (le) (rate(krabka_broker_delivery_activation_lateness_seconds_bucket[5m])))
rate(krabka_broker_delivery_scheduler_wakeups_total[5m])
krabka_broker_delivery_pending_records
krabka_broker_delivery_clock_uncertainty_seconds
The wakeup counter is what separates the two causes: a scheduler that never
ran and one that ran late. A flat wakeup rate with a growing
delivery_pending_records is the first; a healthy wakeup rate with a high
lateness quantile is the second.
Diagnose
- Scheduler not running. Look for the broker being CPU-starved as a whole: request latency up across every API points at the node rather than at delivery — see broker-saturation.
- Scheduler running late. The wake is timer-driven, so a late wake is a
loaded runtime.
krabka_broker_in_flight_requestsand the phase histograms say whether handlers are occupying the executor. - Clock.
delivery_clock_uncertainty_secondsis the KFC-8 bound the broker declares and adds before a batch activates. If a measured clock error on the node exceeds it, the bound is not honest and the lateness is the truth catching up. Compare with the node’s own NTP or PTP offset. - Leadership churn. A partition whose leader moved re-arms its schedule
on the new leader. A burst of lateness that coincides with
krabka_broker_isr_shrinks_totalor a preferred-leader election is that, and it does not persist.
Fix
- For CPU starvation, take load off the broker: move partitions, raise the quota that is not throttling, or add a broker. The scheduler competes with request handlers for the same runtime.
- For clock error, fix time sync on the node first, then raise the declared uncertainty bound only if the true error cannot be brought inside it. A bound that is honest and wide is safer than one that is tight and wrong.
- For a topic whose deadlines are simply tighter than the broker can serve,
delivery.max.delay.msbounds how far ahead a batch may be scheduled but does not make activation faster. The fix is capacity.
Escalate
Lateness that persists on an idle broker with a healthy wakeup rate and a
clock inside its bound is a scheduler bug. Capture the quantile, the wakeup
rate, the pending-record gauge and a CPU profile from /debug/pprof/profile,
and open an issue: the guarantee the topic sells is what is failing.