Skip to content
About
Main content

Stragglers: two regimes that need different answers

How do random and deterministic stragglers differ, and how does peer comparison tell them apart?

A is a task or node that finishes much later than its peers. Mixing up the two kinds is a common error, so separate them.

Random stragglers are statistical. A request lands behind a pause, a , a scheduler hiccup or a cold page. Any node can produce one, and the identity of the slow node is uncorrelated across requests. The right response is redundancy in time: (send a second copy of a slow request to another node and use whichever answers first), , and speculative re-execution. These work precisely because independence holds: a second attempt lands on a different node whose delay is uncorrelated with the first. (The mechanism is hedging; its budget and its off switch under overload are in retry and hedge budgets.)

Deterministic stragglers are a property of a node: the throttled NIC, the dying disk, the host with a noisy neighbor. The identity is stable across requests. Hedging is now nearly useless. It doubles load, and in a scatter-gather where the query must touch every shard it cannot avoid the bad node, because there is no alternative replica for that shard's data. Worse, hedging under a deterministic straggler adds load to a system that is already short of capacity. This mitigation is correct in one regime and harmful in the other: the regime-flip principle, cleanly.

Peer-relative comparison

So the detector must tell them apart, and threshold-based detection cannot. An absolute threshold must be set for the worst legitimate case (the largest partition, the coldest cache), and is therefore far above the signal of a degraded node.

The mechanism that works is peer comparison. Nodes doing similar work are controls for each other. A node that is persistently in the 99th of the peer distribution is a straggler, even if it is comfortably inside its absolute SLO (service-level objective, the promised latency). This is the single most useful detection idea in this article.

Its blind spot is exact: If every node is slow, no node is an outlier, and the detector reports health. So run both: peer-relative detection for and absolute thresholds for systemic degradation. They fail in complementary places, which is the argument for running both instead of choosing.

def slow_peers(latency_p99_by_node, factor=3.0):
    # a node is an outlier if its p99 is more than 3x the median of its peers
    values = sorted(latency_p99_by_node.values())
    median = values[len(values) // 2]
    return [n for n, v in latency_p99_by_node.items() if v > factor * median]