#10276: fix(infra): use bidirectional jitter in computeBackoff
stale
Cluster:
Error Resilience and Retry Logic
## Problem
`computeBackoff` uses unidirectional jitter that only **adds** delay:
```typescript
const jitter = base * policy.jitter * Math.random(); // [0, 1) → always positive
```
This reduces the effectiveness of jitter for preventing thundering herd, as all clients can only delay (not advance) their retries.
## Inconsistency
The same codebase already implements correct bidirectional jitter in `src/infra/retry.ts`:
```typescript
const offset = (Math.random() * 2 - 1) * jitter; // [-1, 1) → bidirectional
```
## Solution
Align `computeBackoff` with the existing `applyJitter` pattern:
```typescript
const jitter = base * policy.jitter * (Math.random() * 2 - 1);
return Math.min(policy.maxMs, Math.max(0, Math.round(base + jitter)));
```
With `jitter=0.2`:
- **Before**: delay range `[base, base × 1.2]` (unidirectional)
- **After**: delay range `[base × 0.8, base × 1.2]` (bidirectional)
The added `Math.max(0, ...)` prevents negative delays when jitter is configured aggressively.
<!-- greptile_comment -->
<h2>Greptile Overview</h2>
<h3>Greptile Summary</h3>
- Updates `computeBackoff` (`src/infra/backoff.ts`) to use bidirectional jitter: the jitter term can now be negative or positive instead of always increasing delay.
- Adds a lower clamp (`Math.max(0, ...)`) before applying `policy.maxMs`, preventing negative delays when jitter is configured aggressively.
- Aligns backoff jitter behavior with the existing bidirectional jitter logic used elsewhere in infra retry utilities.
<h3>Confidence Score: 5/5</h3>
- This PR is safe to merge with minimal risk.
- Change is small, localized to backoff jitter calculation, and now clamps negative delays to 0. Callers already clamp jitter to [0,1] in at least the primary config path, and the new behavior matches the existing bidirectional jitter pattern in infra retry utilities.
- No files require special attention
<!-- greptile_other_comments_section -->
<sub>(5/5) You can turn off certain types of comments like style [here](https://app.greptile.com/review/github)!</sub>
<!-- /greptile_comment -->
Most Similar PRs
#12995: feat(infra): Add retry with exponential backoff for transient failures
by trevorgordon981 · 2026-02-10
78.9%
#4086: Test/add backoff tests
by TechWizard9999 · 2026-01-29
75.7%
#16195: feat(infra): add unified retry utility with exponential backoff
by bianbiandashen · 2026-02-14
71.1%
#15585: fix: add retry/backoff for Gemini embedding API calls
by WalterSumbon · 2026-02-13
70.9%
#9025: Fix/automatic exponential backoff for LLM rate limits
by fotorpics · 2026-02-04
69.9%
#11874: fix: handle fetch rejections in provider usage withTimeout
by Zjianru · 2026-02-08
69.1%
#11752: fix(heartbeat): clamp setTimeout delay to 2^31-1 to prevent Timeout...
by kjaylee · 2026-02-08
69.0%
#21843: fix: add retry/backoff to Gemini embedding batch API calls
by slegarraga · 2026-02-20
68.8%
#17435: fix(debounce): retry flush with exponential backoff to prevent sile...
by widingmarcus-cyber · 2026-02-15
68.7%
#16913: fix(agent): increase transient HTTP retry from 1 to 3 with escalati...
by hou-rong · 2026-02-15
68.6%