The job queue behind the work modern apps depend on.
Six common patterns SimpleQ handles — publish a job over HTTP and we deliver it to your webhook with retries, per-queue rate limiting, and backpressure. Copy-paste API calls for each.
AI job processing
LLM calls are slow, fail intermittently, and hit token-per-minute rate limits at the worst moments. Doing them inline blocks user requests, kills timeouts, and silently drops work when a worker restarts.
Publish AI jobs to a queue with rate limiting. SimpleQ delivers each job to your webhook, handles 429/503/529 backpressure without burning retries, and gives you per-job logs with payloads, attempts, and latency. Use the built-in OpenAI or Anthropic queue template for preconfigured settings.
1# Publish an AI job — SimpleQ delivers it to your webhook2curl -X POST https://api.simpleq.io/v1/queues/ai-jobs/jobs \3 -H "Authorization: Bearer sq_live_abc123..." \4 -H "Content-Type: application/json" \5 -d '{6 "payload": {7 "model": "gpt-4o-mini",8 "messages": [{ "role": "user", "content": "Summarize this" }],9 "userId": "u_123"10 },11 "idempotencyKey": "summary_req_456"12 }'AI agent pipelines
A multi-step agent run chains LLM calls, tool calls, and downstream APIs. Run it inline and one slow step, a 429, or a crash takes down the whole run — with no way to resume from where it failed.
Publish each step as a job with an idempotency key. SimpleQ delivers it to your webhook, retries transient failures with backoff, and defers on backpressure so a rate-limited model call waits instead of failing. Every step is durable and replayable from the dashboard — a crash never loses the run.
1# Queue a step in an agent run — the idempotency key makes retries safe2curl -X POST https://api.simpleq.io/v1/queues/agent-steps/jobs \3 -H "Authorization: Bearer sq_live_abc123..." \4 -H "Content-Type: application/json" \5 -d '{6 "payload": {7 "runId": "run_5f21",8 "step": "summarize-and-route",9 "input": { "threadId": "thr_889" }10 },11 "idempotencyKey": "run_5f21_step_3"12 }'13 14# SimpleQ POSTs the step to your webhook; your worker runs it and15# enqueues the next step. A crash mid-run redelivers — never duplicates.Bulk API sync
Syncing thousands of records to Stripe, Salesforce, or a CRM means hammering rate limits, watching jobs die halfway, and writing custom resume logic every time.
Create a queue with rate limiting. Fan out each record as a job. SimpleQ paces delivery to your webhook (which calls the downstream API), retries failures, and tracks every attempt — no custom checkpointing required.
1# Create a rate-limited queue for Stripe sync2curl -X POST https://api.simpleq.io/v1/queues \3 -H "Authorization: Bearer sq_live_abc123..." \4 -d '{5 "name": "billing-sync",6 "webhookUrl": "https://your-app.com/stripe-sync-handler",7 "maxAttempts": 5,8 "rateLimitMax": 50,9 "rateLimitWindow": 60,10 "dlqEnabled": true11 }'12 13# Fan out — publish one job per customer14for id in customer_001 customer_002 customer_003; do15 curl -X POST https://api.simpleq.io/v1/queues/billing-sync/jobs \16 -H "Authorization: Bearer sq_live_abc123..." \17 -d "{\"payload\": {\"customerId\": \"$id\"}}"18doneDelayed jobs
You need to run a job later — reconcile a payment 30 minutes after checkout, expire a hold a few hours out, or kick off an end-of-day sync. Tracking those timers yourself means standing up extra infrastructure and one more thing to monitor.
Publish a job with a delay in seconds, up to 24 hours out. SimpleQ holds it in pending until the delay expires, then delivers it to your webhook — one-shot, with full retry and DLQ support.
1# Reconcile a payment 30 minutes after checkout2curl -X POST https://api.simpleq.io/v1/queues/deferred-jobs/jobs \3 -H "Authorization: Bearer sq_live_abc123..." \4 -H "Content-Type: application/json" \5 -d '{6 "payload": {7 "orderId": "ord_789",8 "action": "reconcile-payment"9 },10 "delay": 180011 }'12 13# Job stays "pending" for 30 min (max 24h), then SimpleQ POSTs to your webhookBackpressure handling
When a downstream LLM or API returns 429, 503, or 529, most queues count it as a failed attempt — so a rate-limited job burns through its retry budget and dies, and per-attempt pricing spikes at the worst possible moment.
SimpleQ treats 429/503/529 as backpressure: the job defers and redelivers after the Retry-After delay with no attempt burned. A job can ride out a sustained rate limit and still complete without spending its retry budget on backpressure.
1# Create a queue for a rate-limited provider2curl -X POST https://api.simpleq.io/v1/queues \3 -H "Authorization: Bearer sq_live_abc123..." \4 -d '{5 "name": "openai-jobs",6 "webhookUrl": "https://your-app.com/run-llm-job",7 "template": "openai",8 "rateLimitMax": 60,9 "rateLimitWindow": 6010 }'11 12# Your webhook returns 429 with Retry-After: 12 when the provider throttles.13# SimpleQ defers the job 12s and redelivers it — no attempt burned.Ack-mode processing
For long-running work — video processing, large data imports, multi-step AI pipelines — a webhook 200 only means "received", not "done". Without explicit acknowledgment, you can't tell if work actually completed.
Use ack mode. Your webhook returns 200 to confirm receipt, then your app calls /ack when done, /nack to fail fast, or /defer to signal backpressure without burning a retry. If the ack doesn't arrive within the timeout, SimpleQ retries or sends to the DLQ.
1# Create an ack-mode queue2curl -X POST https://api.simpleq.io/v1/queues \3 -H "Authorization: Bearer sq_live_abc123..." \4 -d '{5 "name": "video-processing",6 "webhookUrl": "https://your-app.com/process-video",7 "mode": "ack",8 "ackTimeout": 300,9 "ackTimeoutAction": "retry",10 "maxAttempts": 311 }'12 13# Publish a job → webhook fires → returns 200 → status: "awaiting_ack"14# After processing completes, your app calls:15curl -X POST https://api.simpleq.io/v1/jobs/job_abc123/ack \16 -H "Authorization: Bearer sq_live_abc123..."17# → status: "completed"Ready to ship reliable async work?
Create a queue and run your first job in under five minutes.
Weighing your options? See how SimpleQ compares to SQS, BullMQ, QStash & more →