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
Guzzle Retry Middleware

Guzzle Retry Middleware Laravel Package

caseyamcl/guzzle_retry_middleware

Guzzle Retry Middleware automatically retries Guzzle HTTP requests when servers return 429 or 503, or when requests time out. It honors Retry-After headers, backs off exponentially, supports configurable retry limits and callbacks, and drops into your handler stack with no setup.

View on GitHub
Deep Wiki
Context7

Guzzle Retry Middleware adds automatic retry behavior to your Guzzle v8 request stack. When a server responds with 429 or 503 (or any configurable status code), it intercepts the response and retries up to 10 times by default—honoring a Retry-After header if present, or falling back to exponential backoff. Drop it in with GuzzleRetryMiddleware::factory() and it works with no extra configuration.

  • Retries 429/503 responses out of the box; status codes are configurable
  • Respects Retry-After headers, otherwise backs off exponentially
  • Optionally retries requests that time out
  • Optional callback on each retry for logging or reporting
  • Configurable maximum retry attempts (default: 10)
Frequently asked questions about Guzzle Retry Middleware
How do I install caseyamcl/guzzle_retry_middleware in a Laravel app?
Run composer require caseyamcl/guzzle_retry_middleware. If your app is still on Guzzle 7, which is the default for most Laravel 8+ installs, require version ^2 instead because the latest release targets Guzzle 8. There is no service provider or config publishing step; the package is a single middleware class that you push onto a Guzzle handler stack.
Which package version supports Guzzle 7 versus Guzzle 8?
Version 3.x requires Guzzle 8, while version 2.x supports Guzzle 6 and 7. Stock Laravel 9 through 12 ship Guzzle 7, so composer require caseyamcl/guzzle_retry_middleware:^2 is usually the right constraint. If you have explicitly upgraded to Guzzle 8, use the latest default release.
Does this middleware work with Laravel's Http facade?
There is no first-class Laravel bridge, so you attach the middleware to a Guzzle HandlerStack and give that stack to a client. You can try Http::withOptions(['handler' => $stack]), but that path is undocumented and should be verified on your exact Laravel and Guzzle versions. The safer approach is a singleton Guzzle client or an Http::macro that reuses one configured client.
What is the difference between this and Laravel's Http::retry()?
Laravel's Http::retry only re-fires when an exception is thrown, so a 429 or 503 response is treated as a normal response unless you explicitly call throw(). It also ignores the Retry-After header entirely. This middleware inspects the status code, honors Retry-After delta-seconds and HTTP-date values, and applies configurable backoff.
How do I prevent POST requests from being retried and causing duplicate charges?
Set retry_on_methods explicitly to idempotent verbs such as GET, HEAD, PUT, DELETE, and OPTIONS, or to a per-integration allowlist. The default is '*', which means POST requests are retried and could duplicate charges or orders. Treat this as a required production control before enabling the middleware for any payment or order API.
How does the middleware handle Retry-After headers and backoff?
If the response includes a Retry-After header, the middleware waits for the server's instructed period, supporting both delta-seconds and HTTP-date formats. If the header is absent, it falls back to its configurable backoff schedule. You can override attempts and wait behavior per request, since request options take precedence over client options and middleware defaults.
Can I customize which HTTP status codes trigger a retry?
Yes. retry_on_status defaults to 429 and 503 but accepts any list of status codes. You can set it in the factory options or override it per request through Guzzle request options. That per-request merging is useful for letting individual integrations or tenants tighten or loosen retry rules without rebuilding clients.
How do I log or observe retries in production?
Use the on_retry_callback option to run code each time a retry fires, which is where you can log the URL, attempt number, status code, and wait time. That gives you visibility into retry storms without modifying the middleware itself.
What happens if I combine this middleware with Http::retry() or queue job retries?
Retries multiply. An Http::retry(3) plus a middleware configured for 10 attempts can mean up to 30 outbound calls per request, and queue job $tries stack on top of that. Assign retry ownership to exactly one layer and lower max attempts inside queue workers to avoid hammering an API that is already returning 429.
Is caseyamcl/guzzle_retry_middleware production-ready and actively maintained?
The library is well engineered: PSR-12 compliant, PHPStan level 8, near-100% test coverage, and a maintained changelog. The main risk is governance, since it has roughly 222 stars and a single primary maintainer, so pin a version and review upgrades. Its retry defaults are aggressive for most apps, so tune max_retry_attempts, retry_on_methods, and backoff before production.
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.
ably/pubsub-server
mstfkhazaal/defender
mfonte/base62x
karnoweb/metapilot
tobya/bcsapiwrapper
swalker2/cpanel
vish4395/laravel-translation-manager
morningtrain/economic
teksite/systeminfo-laravel
atomcms/voting
run6/weather
siokas/laravelembeddirectives
adamlien/pkuuids
gilsonsouza/lara-doc-generator
manelgavalda/enrollment_mobile
unabomber/timezone
delatbabel/contacts
astritzeqiri/g-recaptcha
kevinongko/laravel-genode
developeruz/laravel-analytics