Tenant-aware job queues
Keeps delayed and scheduled work within the correct tenant and current authorization even when workers are long-lived and shared.
multi-tenant-queues-scheduling
Team members using this skill
When is it useful?
Use it when one queue serves many workspaces or scheduled actions may outlive the access that originally allowed them.
What does it help you do?
- Requires explicit tenant identity on every scoped job.
- Creates and clears context separately for each worker execution.
- Rechecks membership and entitlements while isolating tenant scheduling failures.
Try asking this
Process two tenants on one worker without retaining the previous tenant’s context. Make the first tenant's job fail, then execute the second. Context cleanup must still run, and the second result must contain only its own records.
Detailed documentation
Read the skill’s original instructions, examples and checks in their authored language.
Show less
Multi-Tenant Queues & Scheduling
When to Use
Use when designing or debugging background jobs, message queues, event subscribers, webhook dispatchers, or scheduled/cron workflows in a multi-tenant system.
1. Mandatory Tenant Envelope on Every Queued Job
Background workers run outside the HTTP request lifecycle. A job without an explicit tenant envelope is a data-leak or crash waiting to happen:
- Required Job Payload Schema:
interface TenantJobEnvelope<T> { tenantId: string; // Mandatory workspace/tenant identifier actorId: string | null; // User or service principal who triggered the job actorType: 'user' | 'api_key' | 'system'; enqueuedAt: string; // ISO timestamp correlationId: string; // Trace/request ID payload: T; } - Reject job enqueue calls for tenant-scoped job types if
tenantIdis missing.
2. Worker Context Initialization, Cleanup & State Hygiene
Long-lived worker processes execute jobs for Tenant A, then Tenant B, then Tenant C sequentially or concurrently in the same OS process:
- Per-Job Context Scope: Wrap every job execution in a fresh
AsyncLocalStorage.run(jobTenantContext, ...)(orcontextvars/ DB transactionSET LOCAL app.current_tenant_id) and ensure context exits cleanly intry / finally. - Zero Worker-Global Mutable State: Never cache tenant data, auth clients, or temp files on module-level variables inside a worker without keying by
tenantIdand cleaning up after the job finishes.
3. Time-of-Check vs. Time-of-Execution (TOCTOU) Re-Verification
A job enqueued today (or scheduled for 24 hours later) may execute after:
- The workspace was
suspendedordeleted. - The workspace's subscription lost entitlement to the feature.
- The user who scheduled the action was removed from the workspace or had their role downgraded.
At the start of worker execution, re-verify:
- The workspace exists and is
active(ifsuspendedordeleted, abort/cancel the job cleanly without retrying). - For user-attributed delayed mutations (exports, scheduled sends, bulk edits), verify whether the initiating user or token still holds permission according to the domain policy.
4. Fan-Out Scheduling Pattern for Cron Jobs
Never run a single monolithic cron query that loads all rows across all 5,000 workspaces into one giant in-memory array (SELECT * FROM items WHERE due_at < NOW()):
- One corrupt record or slow external API in
Workspace #42will crash or block the cron job for all other 4,999 workspaces! - Dispatcher $\rightarrow$ Per-Tenant Job Fan-Out:
- The scheduler queries only active
workspace_ids that have due work (SELECT DISTINCT workspace_id ...). - It enqueues an isolated per-workspace job (
process-tenant-digest,{ tenantId }) with deterministic idempotency key (digest:${tenantId}:${dateWindow}). - Each workspace job runs in its own isolated tenant context, transaction, and error boundary.
- The scheduler queries only active
5. Noisy-Neighbor Fairness & Per-Tenant Concurrency Limits
Prevent a single tenant enqueueing 50,000 jobs from starving all other tenants:
- Enforce per-tenant rate limits or per-tenant active concurrency caps in the queue consumer, or separate fast interactive queues from bulk batch queues.
Included files 1
SKILL.md
