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 Advanced Throttle Laravel Package

hamburgscleanest/guzzle-advanced-throttle

Advanced Throttle adds flexible rate-limiting middleware to Guzzle, letting PHP and Laravel apps enforce multiple request limits, use cache or Redis storage, and avoid API overages with configurable buckets, per-host rules, and smooth request spacing. Ideal for reliable API clients.

View on GitHub
Deep Wiki
Context7

Product Decisions This Supports

  • Which integrations ship now vs. later. Every outbound third-party API (payments, CRM, marketplace, ads, LLM providers, shipping/logistics) has a quota. A rule-based throttle middleware turns "we can't ship this sync until we negotiate a higher tier" into "we ship at the partner's published limit and let the middleware queue and pace the calls." That shifts a commercial dependency into an engineering one.
  • Build vs. buy for rate-limit plumbing. The core value proposition is not the throttle — it's the multi-rule + cache-fallback combination. Deciding to adopt this is a decision to not own ~200–400 lines of concurrency-sensitive code, Redis-backed counters, per-rule window bookkeeping, and exception handling around 429s. For a small team, that's a defensible buy.
  • Graceful degradation as a product behavior. The caching strategy is the interesting bit strategically: "return last-known-good response when the limit is hit" lets you keep a UI populated (stale prices, stale counts, stale profile data) instead of showing an error or a spinner. That is a product decision — how fresh does this screen need to be? — and this package makes it cheap to implement and cheap to reverse.
  • Per-integration configuration as a first-class surface. Because rules are declared in config, you can expose them per tenant, per environment, or per plan tier. That supports entitlement decisions ("Pro gets 10 syncs/min, Team gets 60") without new code paths.
  • Roadmap sequencing for background work. Batch imports, backfills, nightly enrichment, and webhook fan-out all compete for the same partner quota as user-triggered actions. A throttle layer lets you make an explicit roadmap decision about how much quota is reserved for interactive traffic vs. jobs, rather than discovering it in production.
  • Incident and support posture. Most "the integration is broken" tickets are actually 429 storms or quota exhaustion. Adopting a throttle with a cache fallback reduces a noisy, hard-to-explain failure class into a documented, monitorable one.
  • Concrete use cases worth scoping against this: multi-tenant SaaS syncing to a single partner account (where all tenants share one quota); marketplace/ERP order import; enrichment pipelines calling an API with a hard per-minute cap; AI feature calls with a tokens-per-minute ceiling; any place where "show yesterday's cached data" beats "show an error."

When to Consider This Package

Adopt it when:

  • Outbound HTTP goes through Guzzle — either directly or via Laravel's Http client, which is Guzzle underneath. Note the integration is not a first-class Laravel facade feature; you attach middleware to the underlying handler/client, so budget a small spike to confirm the wiring works cleanly for your Laravel version.
  • You talk to multiple APIs with different limits, or to one API with several distinct limits (per-minute and per-day, or per-endpoint), and you want them expressed as declarative rules rather than scattered sleep() calls.
  • You genuinely want the cache-fallback semantics: serve the cached response when the limit is exceeded, or always serve from cache to preserve quota for writes. This is the differentiator; if you don't need it, the package is overkill.
  • You run distributed workers and need a shared counter (a Redis cache store) rather than per-process throttling that adds up to N× the real limit.
  • Your team is small enough that owning throttle primitives is a real distraction, and you're willing to wrap the dependency behind an internal interface so it stays replaceable.
  • Request volume fits inside a cache-store counter pattern — this is orchestration, not traffic shaping at scale.

Look elsewhere — or build in-house — when:

  • You only have one API and one limit. RateLimiter / Redis::throttle() in Laravel, or a few lines of your own, is simpler, has no supply-chain surface, and you already own it.
  • You need retry, exponential backoff, jitter, and circuit breaking, not just pacing. Guzzle's RetryMiddleware, caseyamcl/guzzle_retry_middleware, or Laravel's Http::retry() cover that; throttling is a different concern and mixing them adds confusion.
  • You're not on Guzzle. If you're on Symfony HttpClient, the Symfony RateLimiter component is the native answer.
  • You need observability. No metrics, tracing, or queue-aware scheduling out of the box. If you need dashboards for "which partner are we throttling and how often," plan to instrument it yourself or use an API gateway.
  • Staleness is unacceptable. For balances, inventory availability, prices shown at checkout, or anything with financial or compliance consequences, the "always return cached value" mode is a correctness bug with a friendly name. Only use it where the product explicitly tolerates stale reads.
  • Maintenance risk is a blocker. The signals here are thin — a single maintainer, low dependent count, and no meaningful ecosystem gravity. Treat it as a vendored, pinned, wrapped dependency: lock the version, fork if needed, put it behind your own Throttler interface, and keep a ~2-day exit path. Do not let it become load-bearing without tests around your usage. Verify it supports your Guzzle major version and is compatible with your PHP version before committing — the middleware API has shifted across Guzzle versions.
  • You need strict fairness or per-tenant SLAs. A shared bucket is not a scheduler. Guaranteeing that tenant A's sync doesn't starve tenant B requires queueing and prioritization this package doesn't provide.

How to Pitch It (Stakeholders)

For executives — the one-paragraph version: Every external API we integrate with enforces a request quota, and when we exceed it, the integration fails and so does the customer-facing feature that depends on it. This is a small, focused library that paces our outbound calls to each partner's published limits and, where the product can tolerate it, serves the last known response instead of an error. Adopting it lets us ship quota-constrained integrations sooner, at lower partner tiers, and it converts a recurring class of "it's broken" support tickets into a controlled, explainable behavior. Cost is roughly a day of integration and test work versus one to two weeks to build and then permanently own the equivalent. The main caveat is that it's a low-adoption, single-maintainer package, so we adopt it behind our own internal wrapper and pin the version — we get the benefit without the lock-in.

For engineering — the summary: A Guzzle middleware that enforces one or more declarative throttle rules and adds a cache strategy: on rate-limit exhaustion, return the cached response; or always serve from cache to conserve quota for writes. It slots into our stack because Laravel's Http client is Guzzle-based, though it needs to be attached at the handler level rather than through the facade — validate that wiring first. It does not do retries, backoff/jitter, circuit breaking, metrics, or per-tenant fairness; pair it with a retry middleware and instrument it. Because the dependency signals are weak — one maintainer, near-zero dependents — the ask is: wrap it behind an internal Throttler interface, pin the version, cover our usage with tests against a fake handler, and confirm Guzzle/PHP compatibility up front so swapping it out later is an afternoon, not a project.

For product — the framing: The cache-fallback mode is a UX lever, not just an infrastructure setting. The question it forces is "how stale can this be before it's wrong?" — and answering that per surface (a dashboard count is fine at 5 minutes; a checkout price is never fine) is the actual decision. Default to hard-failing on anything transactional, and use the stale-serve path for read-only, tolerance-friendly views.

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.
3mdikram/worldmoneywords
snowsoft/config
itmosoft/laravel-subscriptions
larva/laravel-ai-qwen
diephp/sequences
users-au/socialite-provider
twidpay/twid-logger
mrnewport/laravel-plaid
mrnewport/laravel-repo
mrnewport/laravel-docsign
mrnewport/laravel-stow
mrnewport/laravel-flow
mrnewport/laravel-priceable
mrnewport/laravel-nestedterms
fredmeng/laravel-apidoc-generator
itstructure/laravel-multilingual-tools
pdustdar/elasticsearch
markupai/php-sdk
rlacerda83/lumem-microservice-shipment
uni-method/symfony-lib