Context
Issue #866 decided the cron architecture: time-critical (Class A) jobs move to QStash, business-cadence jobs stay on GitHub Actions, Inngest is the Phase-2 option, and Temporal is rejected. ADR 14 sanctions QStash without a broker. The 2026-07-17 audit re-validated those decisions against the 2025/2026 landscape and found them reinforced: Temporal still requires always-on workers a Netlify monolith cannot host and its cloud pricing added plan minimums; Upstash discontinued serverless Kafka in March 2025, steering to QStash; QStash offers per-message retries, DLQs, per-minute cron with CRON_TZ, and absolute-time delivery up to a year out via Upstash-Not-Before — the exact semantic appointment reminders need. QStash remains uninstalled.
Proposed approach
Install QStash and migrate the Class-A set per #866: tentative cleanup and payment reconciliation to QStash cron against the existing HTTP endpoints, waitlist expiry to a Not-Before message per offer with the slow sweep as backstop, and reminder fan-out to one Not-Before message per reminder published from the booking write path (the hourly GitHub Actions workflow added in the lifecycle PR is the interim). Record Netlify Async Workloads (now GA, delayUntil up to one year, but no cron and opaque credit pricing) and Upstash Workflow as fallbacks in the ADR.
Per #866 and ADR 14; audit area 5. Found alongside #998.
Context
Issue #866 decided the cron architecture: time-critical (Class A) jobs move to QStash, business-cadence jobs stay on GitHub Actions, Inngest is the Phase-2 option, and Temporal is rejected. ADR 14 sanctions QStash without a broker. The 2026-07-17 audit re-validated those decisions against the 2025/2026 landscape and found them reinforced: Temporal still requires always-on workers a Netlify monolith cannot host and its cloud pricing added plan minimums; Upstash discontinued serverless Kafka in March 2025, steering to QStash; QStash offers per-message retries, DLQs, per-minute cron with CRON_TZ, and absolute-time delivery up to a year out via Upstash-Not-Before — the exact semantic appointment reminders need. QStash remains uninstalled.
Proposed approach
Install QStash and migrate the Class-A set per #866: tentative cleanup and payment reconciliation to QStash cron against the existing HTTP endpoints, waitlist expiry to a Not-Before message per offer with the slow sweep as backstop, and reminder fan-out to one Not-Before message per reminder published from the booking write path (the hourly GitHub Actions workflow added in the lifecycle PR is the interim). Record Netlify Async Workloads (now GA, delayUntil up to one year, but no cron and opaque credit pricing) and Upstash Workflow as fallbacks in the ADR.
Per #866 and ADR 14; audit area 5. Found alongside #998.