serendipity_hq/component-then-when
Serendipity HQ's Component Then When adds fluent then() and when() helpers to Laravel components, letting you chain conditional logic and post-processing directly in component definitions. Lightweight and easy to drop in, it means cleaner, more expressive code with less boilerplate.
Feature scoping: retry/backoff as an enabling capability, not a headline feature. The package answers one narrow question — "when should the next attempt happen?" — so it informs whether reliability work is a differentiator or table stakes. For most B2B/API-integration products, deterministic backoff with jitter is table stakes; budget it as an enabler for things like webhook delivery, third-party API calls, notification fan-out, and async job retries, not as a roadmap item a customer would pay for.
Build vs. buy vs. borrow. This is a small algorithmic component (next-attempt timestamps from attempt count and policy). The scoring signals (2 stars, 0 dependents, low opportunity) say the ecosystem does not treat this as a hard problem, so treat the package as a reference implementation and vocabulary source first, and a dependency second. The realistic options:
Architecture decision: keep retry policy behind an interface. Whatever the choice, the PM-relevant outcome is that the "when is the next attempt?" decision is a swappable seam — one class behind a RetryPolicy-style contract. That converts a low-reversibility decision (baked-in time math scattered across jobs) into a high-reversibility one, and lets you change strategy per integration (aggressive for internal services, slow-and-jittered for rate-limited vendors).
Roadmap input for reliability/SLA commitments. If you're publishing delivery guarantees ("webhooks retried with exponential backoff for 24h"), the policy becomes an externally visible contract. That is a product commitment, not an implementation detail — the package can supply the math, but the policy (max attempts, total window, jitter, dead-letter behavior) needs a product owner and documentation.
Risk/portfolio decision. Low adoption plus a single maintainer means this should not sit on a critical path. Acceptable on secondary paths (email retry, analytics sync, non-critical webhooks); not acceptable as the only thing between you and lost payments or lost orders.
Reasonable fit when:
Look elsewhere (or implement in-house) when:
backoff(), retryUntil(), and maxExceptions; the scheduler and RateLimiter cover most throttling. If your need is "retry this job with backoff," adopting a package adds a dependency for something the framework does.Before committing, run a two-day spike: read the actual algorithm and tests, verify behavior at attempt 0/1, at the cap, and past exhaustion; check integer overflow and overflow-safe timestamp handling; confirm jitter is present and configurable; confirm no hidden container/global state; confirm the PHP version floor matches your runtime. If the spike is longer than writing it yourself, the build-vs-buy answer is settled.
To executives (one paragraph): This is a small, free (MIT), single-purpose utility that calculates when to retry something that failed — the timing logic behind webhook redelivery and third-party API retries. It is not a product feature and not a customer-visible differentiator; it's plumbing that prevents us from hand-rolling retry timing, where subtle mistakes (no jitter, unbounded growth, overflow) turn into thundering-herd incidents and duplicated charges. Cost is zero in license fees and near-zero in integration; the real cost is a low-adoption, single-maintainer dependency. Recommendation: adopt on secondary paths behind our own interface, or reimplement — either way we own the policy and can swap the implementation in an afternoon. No headcount, no schedule impact, and it de-risks a class of reliability bugs we would otherwise only find in production.
To engineering (the substance): The package computes the time of the next retry for fault-tolerant flows — a stateless "given attempt count and policy, return next attempt time" calculator. Treat it as a replaceable seam: wrap it in a thin RetryPolicy contract in our domain, so no job or client calls it directly. That gives us (a) a one-file swap if the package stalls, (b) per-integration policies, and (c) a single place to unit-test edge cases: first retry, cap ceiling, exhaustion, overflow at large attempt counts, and jitter distribution. Where Laravel's queue backoff()/retryUntil() already express the policy, prefer the framework and use this only where we need the calculation outside a queue context (synchronous HTTP clients, schedulers, custom workers). Pin the version, add a smoke test asserting monotonic growth and bounded max delay, and note in the ADR that this is a low-adoption dependency accepted for a non-critical path only.
How can I help you explore Laravel packages today?