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

Laravel Http Remember Laravel Package

philipannis/laravel-http-remember

A small Laravel package that brings Cache::remember-style caching to the HTTP client. Cache outgoing API responses per request with a configurable TTL and cache store, then serve repeated calls from cache to reduce latency, duplicate requests, and load on rate-limited third-party APIs.

View on GitHub
Deep Wiki
Context7

Getting Started

  1. Install with composer require philipannis/laravel-http-remember and publish the config (php artisan vendor:publish --tag=... — confirm the tag in the README).
  2. Read config/http-remember.php before writing any code. It now covers conditional caching, ignored headers, size limits, event logging, manual invalidation, miss deduplication, refresh cooldown/retry-after, and log redaction.
  3. Skim the README sections on invalidation and the new v1.0.3 features. Group invalidation is still the headline feature; manual invalidation and deduplication are the new day-to-day tools.
  4. If you're upgrading, diff your published config against the new one first. v1.0.3 adds keys with defaults, and the new "reject unsafe header exclusions" behavior (PR #22) can invalidate existing ignored_headers entries — see Gotchas.

First use case: cache an expensive outgoing HTTP call (or a controller response) that is identical for many users — e.g. a third-party currency rates or catalog endpoint — and invalidate it as a group when the upstream data changes. Start with a single remember-style call, verify a cache hit on the second request, then layer in groups and conditions.

If you're evaluating the package, confirm three things first: which cache store you'll use (group invalidation still depends on it), whether you need per-user or shared caching, and whether your expected traffic has thundering-herd characteristics (in which case enable deduplication from day one).

Implementation Patterns

Basic caching. Wrap the call in the package's remember API, supplying a key, TTL, and a closure that performs the request. Keep the closure pure — it may be skipped entirely on a hit, so don't put side effects (logging, counters, model writes) inside it.

Group invalidation. Assign each cached entry to one or more logical groups (e.g. products, tenant:42) and flush a group when the underlying data changes. Standardize on this: observers/model events call the group flush, and HTTP-layer code never worries about individual keys. Design group names as stable, low-cardinality strings.

Manual invalidation (v1.0.3). For cases where a whole group is too blunt — one product changed, one tenant's settings were edited — use the new manual invalidation API to forget specific keys. Typical pattern:

  • Group flush for "the upstream catalog was resynced."
  • Manual key invalidation for "product 42 was edited." This lets you keep TTLs long on hot single entities without flushing neighbours. Wrap both in a small repository so callers never build keys by hand.

Cache miss deduplication (v1.0.3). When a hot key expires, all concurrent requests would otherwise stampede the upstream. Enable deduplication so only one request refreshes while others wait for or reuse the result. This is essentially mandatory for expensive upstreams under load; combine with a short lock TTL so a hung upstream doesn't block forever. Watch for the failure mode where the "winning" request errors and everyone behind the lock gets the error — make sure your fallback path is well-tested.

Refresh cooldown and retry-after (v1.0.3). Use the cooldown to prevent refresh storms (a burst of misses triggering repeated upstream calls) and to respect upstream rate limits. Have your closure surface Retry-After so the package can back off the right amount; then verify behaviour when the upstream returns 429/503 by asserting on events, not just on the cache contents.

Conditional caching. Use the conditional hooks to decide at runtime whether a response is cacheable:

  • Only cache successful responses (2xx).
  • Skip caching when the response contains user-specific or volatile data.
  • Skip caching when an auth/session context changes the meaning of the response.

Keep the condition cheap and deterministic; it runs on every request.

Ignored cache key headers. Normalize the cache key by excluding headers that don't affect the response body (request IDs, trace headers, User-Agent if you don't vary on it). This dramatically improves hit rates with noisy clients. v1.0.3 adds rejection of unsafe exclusions (see Gotchas) — the guardrails now protect you, but be prepared for config-load failures during upgrade.

Response size limit. Set a ceiling so a single huge upstream payload can't blow up the cache store or evict everything else. Treat the limit as a guardrail, not a tuning knob — if you're consistently near it, the endpoint probably shouldn't be cached wholesale.

Log redaction (v1.0.3). Enable redaction for anything sensitive that appears in lifecycle logs (auth headers, query-string tokens, PII in URLs). If you have custom event listeners that log the full request, redaction won't save you — audit those too.

Event logs. Use lifecycle events (hit/miss/store/skip/refresh/dedup) for:

  • Local debugging: listen and dump to the log to see why a request missed.
  • Metrics: hit ratio per group, skips by reason (size limit, condition), refresh counts, dedup waits, redacted-field counts.
  • Tests: assert an event fired rather than asserting on the cache store directly.

Integration tips.

  • Wrap outgoing calls in a small repository/service class so caching policy lives in one place.
  • In tests, use the array cache driver and Cache::flush() between tests; assert hit/miss via events.
  • Pair group flushes with model observers so invalidation is automatic and colocated with writes; use manual invalidation for single-entity edits.
  • For multi-tenant apps, include the tenant identifier in both the cache key and the group name.
  • Add a test that runs the dedup path under simulated concurrency (parallel processes hitting an empty cache) so you catch lock leaks before production.

Gotchas and Tips

Unsafe header exclusions are now rejected (v1.0.3). PR #22 introduces validation of ignored_headers. The upside: the previous "footgun in reverse" is largely closed off. The downside: a config listing a header the package now considers unsafe (typically Authorization, Cookie, Accept, Accept-Language, Vary-relevant headers) may throw at config load or be dropped with a warning. Re-test the app immediately after upgrading; check the README for the exact list and the exact failure mode (exception vs. silently ignored). This is the most likely source of upgrade pain.

Group invalidation still requires a taggable cache store. Laravel's file and database stores do not support cache tags. If group invalidation is implemented via tags, it will silently degrade or throw depending on the store. Use Redis or Memcached in production, and make sure your test environment matches — an array store supports tags, so tests can pass while file fails in staging. Manual invalidation (v1.0.3) works on any store, but only if you know the exact key.

Silent skips. Conditional caching and the response size limit both cause entries to be not cached, without an error. Events are your only visibility. In production, count skips per reason and alert if the skip rate spikes — it usually means an upstream change (bigger payloads, new error shape).

Deduplication can turn a small upstream error into a big outage. If the lock holder fails, every waiter may inherit the failure. Add a fallback path (serve stale, or a short TTL fallback to a known-good value) and test the lock-holder-fails case explicitly.

Cooldown vs. correctness. A refresh cooldown means a key may keep serving a stale value after an invalidation, if the invalidation triggers a refresh that is throttled. For writes with a strong consistency requirement, combine manual invalidation with an explicit forget rather than relying on refresh.

Cache key collisions. If keys are derived from URLs/methods only, two different auth contexts can collide. Always include the dimensions you vary on, and verify by testing with two different users.

TTL vs. invalidation. Prefer short TTLs plus explicit group flushes over long TTLs alone, especially for data with a known write path. Long TTLs turn a missed invalidation into a stale-data incident.

Event log volume and log content. Lifecycle events fire on every request; in high-traffic apps, log listeners can become a bottleneck. Gate verbose logging behind a config flag or sample it, and push metrics to your APM rather than the default log channel. Redaction matters here — if you log at high volume and forget to redact, you're leaking credentials to disk on every request.

Extension points to know. Look for the custom key resolver and the event classes; these are the cleanest seams for app-specific behaviour (custom key strategies, custom metrics, custom invalidation endpoints). Avoid forking the package for these; both are meant to be overridden.

Upgrade note (1.0.2 → 1.0.3). Additive features, but two of them change runtime behaviour: unsafe header exclusion rejection can break existing configs, and deduplication/cooldown changes the timing of upstream requests. No explicit breaking-change marker in the changelog, but treat it as a "re-test your caching config" release. Diff your published config, check the safe/allowed header list in the README, and run one happy-path and one failure-path test against deduplication and retry-after before rolling out.

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.
uni-method/symfony-lib
tacticmedia/scim-server-bundle
neika-ai/symfony-bundle
mattleads/agent-publishing-bundle
glavweb/framework-bundle
glavweb/extra-bundle
glavweb/api-bundle
glavweb/admin-bundle
adachsoft/api-version-bundle
elsayed85/laravel-api-exceptions
ouhssini/laravel-demo-mode
daworks/ncloud-outbound-mailer-driver
gp247/cms
ignibyte/aic-gates
nexa-merchant/blog
novasa/laravel-language-center
opencage/geocode
adolfoholzer/parameters
livenetworks/ln-starter
shitoudev/permissionmanager