Skip to content

[14.x] Add opt-in jitter to queue backoff - #61437

Closed
yousefkadah wants to merge 1 commit into
laravel:masterfrom
yousefkadah:feat/queue-backoff-jitter
Closed

[14.x] Add opt-in jitter to queue backoff#61437
yousefkadah wants to merge 1 commit into
laravel:masterfrom
yousefkadah:feat/queue-backoff-jitter

Conversation

@yousefkadah

Copy link
Copy Markdown
Contributor

Backoff delays are currently deterministic. Every job that fails at the same moment against the same dependency computes the same delay and retries in lockstep, so a rate-limited or briefly-degraded API gets hit by the whole batch again simultaneously.

This adds an opt-in jitter ratio that spreads those retries over a bounded window around the configured backoff.

use Illuminate\Queue\Attributes\Backoff;
use Illuminate\Queue\Attributes\BackoffJitter;

#[Backoff(60)]
#[BackoffJitter]        // 0.25 by default, so 45-75s
class SyncInventory implements ShouldQueue
{
    //
}

The ratio is configurable, and the property form works too, matching how the other queue options are already expressed:

#[BackoffJitter(0.5)]   // 30-90s

public $backoffJitter = 0.5;

Notes

  • Off by default. With no attribute or property, calculateBackoff() returns exactly what it returned before, so existing retry timing is unchanged.
  • Resolution goes through the existing getAttributeValue() helper, so attribute, property, inheritance, and property-overrides-attribute all behave the same way backoff already does. No new resolution path.
  • A backoff of 0 is left alone, so opting in never introduces a delay where there wasn't one.
  • The ratio is clamped to 0..1, so the delay can't go negative.
  • Jitter is proportional (±ratio) rather than AWS-style full jitter (random(0, backoff)). Full jitter spreads more aggressively but can collapse a deliberately-tuned 300s backoff to near zero; proportional keeps the configured value meaningful. Happy to switch if you'd prefer the other shape.

Tests

tests/Queue 311 passing, tests/Bus and tests/Integration/Queue 378 passing, pint clean. The payload-shape assertions in the Redis, Beanstalkd and Database queue tests were updated for the new key.

🤖 Generated with Claude Code

Backoff delays are currently deterministic, so a group of jobs that fail
together against the same struggling dependency retries in lockstep.

This adds an opt-in jitter ratio, resolved through the same attribute or
property path as the existing backoff options, that spreads those retries
over a bounded window around the configured backoff.

Off by default, so existing retry timing is unchanged.

Co-Authored-By: Claude Opus 5 <noreply@anthropic.com>
@taylorotwell

Copy link
Copy Markdown
Member

Thanks for your pull request to Laravel!

Unfortunately, I'm going to delay merging this code for now. To preserve our ability to adequately maintain the framework, we need to be very careful regarding the amount of code we include.

If applicable, please consider releasing your code as a package so that the community can still take advantage of your contributions!

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

3 participants