Architecture
There is no external job queue — no BullMQ, QStash, Inngest, or worker processes. Deferred work uses after() from next/server, which runs code after the HTTP response has been sent.
Redis advisory locks (leaderboard:lock:{ingestKey}) prevent concurrent ingests from racing each other.
Where after() is used
GET /api/[org]/leaderboard/score
- If precomputed data is fresh: score remaining entity types in background via
after() - If data is stale: trigger
refreshLeaderboardInBackgroundin background viaafter()
POST /api/[org]/leaderboard/recompute (dev-only)
refreshLeaderboardInBackgroundruns after the response viaafter()- Blocked with 403 in production — only available in non-production environments
Both routes set:
export const maxDuration = 300;This allows up to 5-minute serverless function execution on Vercel Pro. The default Hobby plan caps at 60 seconds — large organizations will time out before ingest completes.
Session cleanup
deleteExpiredSessions() is called fire-and-forget inside the OAuth callback:
deleteExpiredSessions().catch(() => {});It is not scheduled. It only runs when a user signs in. If sign-ins are infrequent, expired sessions accumulate until the next login event.
Orphaned maintenance functions
These SQL functions exist in the database but are never called by application code. They must be invoked manually (e.g. via Supabase SQL editor or a migration):
| Function | Purpose | Default |
|---|---|---|
drop_old_signals_partitions(p_keep_months) | Drop signal partitions older than N months | p_keep_months = 12 |
purge_superseded_materializations(p_before) | Delete old leaderboard materializations before a timestamp | — |
purge_expired_auth_sessions() | Delete expired rows from auth_sessions | — |
cleanup_expired_sessions is also orphaned and never called.
None of these are wired to a cron job, scheduled task, or after() call. If you need them to run periodically, you must set up an external scheduler (e.g. Supabase pg_cron, Vercel Cron, GitHub Actions on a schedule).
Leaderboard recompute (debug)
POST /api/[org]/leaderboard/recompute:
- 403 in production — enforced in the route handler
- In non-production: destructive — deletes Redis keys +
signals+ingest_log+leaderboard_materializations+computed_scores, then reruns the full pipeline export const maxDuration = 300
POST /api/debug/recompute (gated by requireDebugAccess):
- Optionally re-ingests: if the request includes the re-ingest flag, deletes
signals+ingest_logbefore recomputing - Available in production only when
ENABLE_DEBUG_ROUTES=trueand the user has a valid session
Summary
| Mechanism | Used for |
|---|---|
after() + Redis lock | Leaderboard ingest / recompute |
Fire-and-forget .catch(()=>{}) | Expired session cleanup on login |
| Manual SQL | DB partition pruning, materialization purge, expired auth sessions |
| None (orphaned) | drop_old_signals_partitions, purge_superseded_materializations, purge_expired_auth_sessions, cleanup_expired_sessions |