19 jobs total — 14 QStash scheduled + 4 QStash triggered + 1 GitHub Actions cron.
All scheduled and event-driven jobs run on QStash (HTTP → Next.js API routes
hosted in
apps/admin, served from admin.theroyalglow.in/api/jobs/*). The
single exception is the pprd branch reset (Job 5), a Neon control-plane op on
GitHub Actions cron. Every job pings a BetterStack heartbeat on success.@rgss/db query functions. The single
exception is the pprd branch reset (Job 5), which is a Neon control-plane op and
runs on GitHub Actions cron.
Where jobs run
- QStash
- GitHub Actions cron
Upstash HTTP queue → Next.js API routes in
apps/admin. Use for ALL scheduled
and triggered jobs (DB maintenance + external services).Every QStash job calls a POST /api/jobs/... route and is auto-retried (3x,
exponential backoff) on a non-2xx response. Every job pings a BetterStack
heartbeat on success so silent failures get detected. The /api/jobs/* routes are
served from admin.theroyalglow.in/api/jobs/*; QStash schedules are registered
from the admin deploy.All schedules are in UTC; the salon operates IST (UTC+5:30).
Not jobs (synchronous / external)
Three time-critical actions deliberately run in-request, not as jobs:- Invoice email + PDF — fired immediately when the receptionist marks payment received.
- Gems-earned push — fired in the same request as invoice completion.
- Re-engagement email — handled inside Brevo automations (marketing), not counted here.
Job inventory
- Scheduled — DB maintenance (7)
- Scheduled — application (8)
- Triggered (4)
These run in the early IST hours when traffic is zero. Jobs 1–4, 6 and 7 run on
QStash (each POSTs its
/api/jobs/... route, which runs the idempotent SQL via
a @rgss/db query function) — not pg_cron. Job 5 runs via GitHub Actions cron
(Neon branch reset) plus SQL anonymisation.Job 1 — Nightly sales summary · 0 18 * * * UTC · 11:30 PM IST
Job 1 — Nightly sales summary · 0 18 * * * UTC · 11:30 PM IST
Aggregate the day’s invoices into
daily_sales_summary. Runs on QStash.Job 2 — Membership auto-expire · 30 18 * * * UTC · 12:00 AM IST
Job 2 — Membership auto-expire · 30 18 * * * UTC · 12:00 AM IST
Flip
spa_membership from active to expired past expires_at. Runs on QStash.Job 3 — Offer auto-expire · 35 18 * * * UTC · 12:05 AM IST
Job 3 — Offer auto-expire · 35 18 * * * UTC · 12:05 AM IST
Deactivate offers whose
end_date has passed. Runs on QStash.Job 7 — Gems auto-expire · 40 18 * * * UTC · 12:10 AM IST
Job 7 — Gems auto-expire · 40 18 * * * UTC · 12:10 AM IST
Deduct gems 365 days after they were earned. Runs on QStash.
Job 6 — Monthly GST summary · 30 19 1 * * UTC · 1:00 AM IST (1st)
Job 6 — Monthly GST summary · 30 19 1 * * UTC · 1:00 AM IST (1st)
Aggregate the prior month into
monthly_gst_summary (SAC 999721). Runs on QStash.Job 5 — pprd DB sync · 30 19 * * * UTC · 1:00 AM IST
Job 5 — pprd DB sync · 30 19 * * * UTC · 1:00 AM IST
GitHub Actions resets
pprd from prod, then strips PII. Control-plane op.Job 4 — Session cleanup · 0 21 * * 0 UTC · 2:30 AM IST Sunday
Job 4 — Session cleanup · 0 21 * * 0 UTC · 2:30 AM IST Sunday
Delete expired Better Auth
session rows. Runs on QStash.Related pages
Jobs API
The QStash-triggered /api/jobs/* route contracts
Data Model
The tables these jobs scan and update
Deployment
How jobs are monitored via BetterStack heartbeats
