Weave Code
Weaver
Helps Laravel developers discover, compare, and choose open-source packages. See popularity, security, maintainers, and scores at a glance to make better decisions.
Feedback
Share your thoughts, report bugs, or suggest improvements.
Subject
Message

Retry Subscriber Laravel Package

guzzlehttp/retry-subscriber

A Guzzle subscriber that automatically retries failed HTTP requests using configurable strategies, including exponential backoff. Set retry limits, delays, and the exceptions or status codes that trigger a retry to make your Guzzle 6/7 API calls more resilient.

View on GitHub
Deep Wiki
Context7

Technical Evaluation

Architecture fit. guzzlehttp/retry-subscriber targets the Guzzle 4/5 event-subscriber architecture (Guzzle\Common\EventSubscriber, Guzzle\Plugin\*). Guzzle 6 replaced that entire extension model with the middleware stack (GuzzleHttp\Middleware::retry, handler composition). The package therefore does not plug into the HTTP layer that any currently supported Laravel release ships with — Laravel 7+ pins guzzlehttp/guzzle: ^7.0, and Laravel 6 pins ^6.5. There is no supported version of Laravel where this package is the natural integration point.

Integration feasibility. Low. Two independent blockers:

  • Composer constraint conflict. The package's require is scoped to Guzzle 4/5 (guzzle/guzzle), while Laravel requires guzzlehttp/guzzle (the renamed, 6+ namespace). These are distinct package names — this is not a version bump, it is a fork boundary. Adoption means either pinning an EOL Laravel or hand-porting the code.
  • Duplication of native capability. The exact feature set (retry count, strategy, backoff) exists natively as Middleware::retry() in Guzzle 6/7 and as Http::retry($times, $sleep, $when) in Laravel's Illuminate\Http\Client. Any capability this package offers is already available with first-party support and security maintenance.

Technical risk. High and mostly non-mitigable:

  • Archived upstream. No security advisories, no PHP 8.x compatibility work, no fixes for Guzzle handler edge cases (stream rewind on retry, non-idempotent body replay). An archived dependency in an HTTP retry path is a supply-chain and correctness liability.
  • Silent retry hazards. Retry logic is a correctness-sensitive concern: retrying non-idempotent POSTs, replaying consumed request bodies, and amplifying load during partial outages. A dormant implementation leaves you owning these bugs.
  • Zero dependents. No ecosystem signal. Nobody else has validated this package against a modern stack, so you are the first integrator — effectively forking and maintaining it yourself.

Key questions.

  1. Is there any concrete behavior here not reproducible with Middleware::retry() or Http::retry() + a custom $when closure? If not, the business case is zero.
  2. If the driver is a legacy service still on Guzzle 5, what is that service's migration timeline — and is patching retries into a dying stack worth the spend?
  3. Who owns this code after adoption? Archive status makes "we'll get upstream fixes" a false assumption.
  4. Does the retry path need body-replay/idempotency guarantees (payments, provisioning)? If so, this package is disqualified regardless of stack.

Verdict: treat as a reference implementation, not an adoption candidate. Low opportunity score with zero dependents is consistent with a superseded package, not an underappreciated one.

Integration Approach

Stack fit. Poor by construction. Recommended target: do not add this dependency. Reimplement the intent on first-party primitives:

Need Native mechanism
Retry in Laravel HTTP client Http::retry(3, 200, throw: false)
Retry in raw Guzzle 7 HandlerStack + Middleware::retry()
Conditional retry $when closure / decider callable
Exponential backoff delay callable (1000 * 2 ** $attempt)

Migration path. If legacy code already depends on the package, sequence it as a removal, not an upgrade:

  1. Inventory every consumer (grep for RetrySubscriber, Guzzle\Plugin, guzzle/guzzle in composer.lock).
  2. Isolate retry policy behind an internal interface (e.g. RetryPolicy::shouldRetry() / delayFor()) so the transport library is swappable.
  3. Port to Middleware::retry() (Guzzle 6/7) or Http::retry() behind that interface.
  4. Delete the dependency; add a CI guard (composer why guzzle/guzzle must be empty) to prevent reintroduction.

Compatibility. No forward-compatibility path exists — Guzzle 4/5 are EOL, do not run on PHP 8, and are not compatible with Laravel's HTTP layer. The only "compatible" scenario is a legacy application frozen on PHP 5.x/7.0 and Laravel ≤5.x, which is itself a remediation item.

Sequencing. Effort is hours-to-days, not a project. Do it opportunistically the next time the affected code path is touched, bundled with an unrelated change, rather than as a standalone initiative. If a legacy Guzzle 5 service exists, its own migration is the real workstream; this package is a leaf node in it.

Operational Impact

Maintenance. Effectively 100% internal ownership on day one — archived upstream means no patch stream. Estimate: a permanent low-grade ownership tax plus unbounded cost if a retry-related incident lands on it. Contrast with the native middleware, where maintenance is bundled into routine Guzzle/Laravel upgrades already on the roadmap.

Support. No maintainer, no issue triage, no CVE channel. Any advisory against Guzzle 4/5 requires you to independently assess exposure and backport. Security review will flag archived dependencies; expect friction at every subsequent audit.

Scaling. Retry logic interacts badly with scale if unconstrained: naive retries multiply load on a degraded dependency (retry storms), and can exhaust PHP-FPM workers on Laravel queues where each retry holds a worker. Native middleware shares this risk, but with the advantage of an actively maintained delay/decider API and documented idempotency guidance. Note the package's own design predates Guzzle's Retry-After handling — you will likely hand-roll that.

Failure modes.

  • Body replay: retrying a streamed request body that has already been consumed → empty or truncated payload sent to the origin. Highest-severity failure mode.
  • Non-idempotent retries: duplicated writes (orders, charges) if retry policy is not method-scoped.
  • PHP version drift: runtime deprecations/fatals on PHP 8+ if the code is force-installed with constraint overrides.
  • Silent no-op: if constraint conflicts are papered over with --ignore-platform-reqs or replace tricks, the subscriber may never be wired into the stack — retries silently don't happen and nobody notices until an incident review.

Ramp-up. Near-zero learning cost (the API is simple), but that is a trap: the low ramp-up makes it look cheap while deferring the real cost to maintenance and incident response. Engineers unfamiliar with Guzzle 4/5 subscribers lose time on a dead architecture with no current documentation.

Recommendation to stakeholders: decline adoption; budget a small remediation task to replace any existing usage with first-party retry middleware, and record the archived-dependency policy gap this surfaced.

Weaver

How can I help you explore Laravel packages today?

Conversation history is not saved when not logged in.
Prompt
Add packages to context
No packages found.
shitoudev/permissionmanager
johannesclimacus/laravel-tui
hocvt/seotools
vitalybaev/sypexgeo
amphibee/themosis-ignition
gito-me/fast-excel
frankyso/laravel-ipaymu
geolize-studio/laravel-chile
boomerangui/chat
jinas/dhivatar
store-doc/laravel-storage-driver
plus-it/laravel-translation-manager
diephp/perhaps
diephp/telegraph
osmaviation/spreadsheet
microsoft/fluentui-system-icons
mmccook/php-json-canonicalization-scheme
middlewares/firewall
qubiqx/montapacking
nyoncode/laravel-package-console