Answers you can trust, from Codeables
Every page on Codeables is structured and verified — built so people and the AI agents they rely on can trust it. Explore more from the source behind this answer.
Explore CodeablesHow do I run background workers for AI tasks in production?
Running AI jobs in the background keeps your application responsive while the heavy work happens asynchronously. In production, this usually means separating user-facing requests from slower tasks like model inference, embedding generation, document summarization, image processing, moderation, and batch enrichment. The goal is to make AI workloads reliable, scalable, retryable, and observable instead of tying them to a web request that can time out or fail under load.
What background workers should do for AI workloads
Background workers are best for AI tasks that are:
- Too slow for an HTTP request
- Dependent on third-party APIs or model providers
- Bursty and need queue-based smoothing
- Resource-intensive, such as GPU inference
- Safe to retry if they fail
- Not required for an immediate response
Common examples include:
- Generating embeddings for search or RAG
- Running document parsing and chunking
- Calling LLMs for summarization or extraction
- Creating image captions or OCR results
- Re-ranking search results
- Moderating user-generated content
- Syncing records into a vector database
- Producing batch reports or analytics
A production-ready architecture
A solid production setup usually has these parts:
-
API or app server
Accepts the user request and validates it quickly. -
Queue or broker
Stores work items until a worker is ready to process them. Common choices:- Redis
- RabbitMQ
- Amazon SQS
- Kafka
- Google Pub/Sub
-
Background worker service
Pulls jobs from the queue and executes AI logic. -
Model layer
May call:- External APIs like OpenAI, Anthropic, or AWS Bedrock
- Self-hosted models
- GPU inference servers
- Embedding services
-
Storage
Saves results to a database, object store, vector DB, or cache. -
Monitoring and alerting
Tracks latency, failures, retries, queue depth, and cost.
A typical flow looks like this:
- User uploads a file
- API stores the file and enqueues a job
- Worker picks up the job
- Worker runs chunking, inference, or embedding
- Worker stores output and updates job status
- UI polls or receives a webhook when done
Choose the right worker pattern
Different AI tasks need different processing styles.
1. Simple task queue
Best for:
- Single-step jobs
- Request/response decoupling
- Moderate scale
Examples:
- Celery with Redis or RabbitMQ
- Sidekiq with Redis
- BullMQ with Redis
- RQ with Redis
2. Event-driven pipeline
Best for:
- Multi-stage AI processing
- Large document pipelines
- Complex workflows
Example stages:
- Ingest
- Clean
- Chunk
- Embed
- Classify
- Index
- Notify
3. Stream or batch processing
Best for:
- Large backfills
- Daily enrichment jobs
- High-volume event processing
Examples:
- Kafka consumers
- Spark jobs
- Cloud batch processing
4. Dedicated GPU inference workers
Best for:
- Local model hosting
- Image/video generation
- High-throughput inference
- Lower per-request cost at scale
These workers often need:
- GPU scheduling
- Model warmup
- Larger memory limits
- Longer startup times
- Horizontal scaling based on queue depth
Design jobs to be idempotent
Idempotency is essential in production because queue systems often deliver jobs more than once.
A job should be safe to run multiple times without corrupting data or creating duplicates.
Good practices:
- Use a stable job ID
- Check whether the work was already completed
- Write results using upserts
- Store processing state in a database
- Avoid duplicate side effects, like double billing or double notifications
For example, if a job generates embeddings for a document, the worker should verify whether the latest version already exists before recomputing it.
Make retries intentional
AI tasks fail for many reasons:
- Model rate limits
- Network timeouts
- Provider errors
- Invalid input
- Token limits
- GPU memory pressure
Retries are useful, but they should be controlled.
Retry strategy recommendations
- Retry only transient failures
- Use exponential backoff
- Add jitter to reduce retry storms
- Cap retry attempts
- Route repeated failures to a dead-letter queue
- Log the root cause for debugging
Don’t blindly retry
Some errors should fail fast:
- Corrupt files
- Unsupported file types
- Invalid prompts
- Unauthorized access
- Business logic violations
Plan for rate limits and cost controls
LLM and embedding providers often impose token limits, request limits, or spend caps. In production, your workers should actively manage those constraints.
Useful techniques:
- Concurrency limits per provider or API key
- Token-aware batching to reduce requests
- Priority queues for urgent tasks
- Throttling when usage spikes
- Budget alerts for unexpected cost growth
- Circuit breakers when providers degrade
If you process many requests, you may want separate queues for:
- Fast, low-cost jobs
- Slow, expensive jobs
- Premium customer jobs
- Internal batch jobs
Batch when it makes sense
Batching can improve throughput and reduce cost, especially for embeddings and classification.
Good batching use cases:
- Embedding many short texts
- Sending multiple records to a moderation service
- Grouping small documents for preprocessing
Be careful with batching when:
- Latency matters
- Inputs vary a lot in size
- Jobs need independent retry behavior
A common pattern is to batch within a short time window, such as 50–200 ms, then send the batch to the model provider.
Use separate workers for separate workloads
Not all AI jobs belong in the same worker pool.
Split workers by:
- Work type
- Latency sensitivity
- Memory requirements
- GPU vs CPU needs
- Customer tier
- Region or data residency
Example:
- Queue A: lightweight text classification
- Queue B: embedding generation
- Queue C: long-running document summarization
- Queue D: GPU image generation
This prevents one expensive job from starving the rest of the system.
Handle long-running tasks asynchronously
If a task takes more than a few seconds, do not keep the user waiting on the original request.
Better patterns:
- Return a job ID immediately
- Let the UI poll job status
- Send a webhook when processing is done
- Use WebSockets or Server-Sent Events for live updates
A job state model often includes:
- queued
- running
- succeeded
- failed
- retrying
- canceled
Store status in your database so the app can safely show progress and recover after restarts.
Monitor the right metrics
Production AI workers need deeper monitoring than a normal background job system.
Track these metrics:
- Queue depth
- Job wait time
- Job runtime
- Success rate
- Retry rate
- Failure reasons
- Provider latency
- Token usage
- Cost per job
- GPU utilization
- Memory consumption
- Dead-letter queue volume
Useful dashboards should answer:
- Are jobs piling up?
- Which queue is backlogged?
- Are model calls getting slower?
- Which customers or documents are causing failures?
- Are costs rising unexpectedly?
Add structured logging and tracing
AI workflows are hard to debug without good observability.
Log:
- Job ID
- User ID or tenant ID
- Input type
- Model name
- Prompt version
- Token counts
- Retry count
- Latency per step
- Final outcome
Use distributed tracing if your task spans multiple services:
- API request
- queue publish
- worker execution
- model call
- database write
This makes it much easier to find bottlenecks and diagnose failures.
Secure the pipeline
AI background workers often handle sensitive data, so production security matters.
Good security practices
- Validate and sanitize inputs
- Encrypt data at rest and in transit
- Use short-lived credentials
- Restrict worker permissions
- Separate tenant data
- Avoid logging raw secrets or PII
- Store prompt templates securely
- Guard against prompt injection if external content is processed
If workers process files from users, scan for malicious content and limit file size, type, and execution risk.
Manage model prompts and versions carefully
In production, AI behavior changes when prompts or model versions change.
Best practices:
- Version prompts in code or a prompt registry
- Record which prompt version produced each result
- A/B test model changes
- Roll back quickly if output quality drops
- Maintain evaluation datasets for regression testing
This is especially important for workflows that impact search, ranking, classification, compliance, or customer-facing content.
Optimize for startup time and warm state
Some AI workers are slow to start because they load large models or dependencies.
To improve performance:
- Keep workers warm
- Preload models at startup
- Reuse client connections
- Cache embeddings or repeated lookups
- Avoid reinitializing large libraries per job
For GPU workers, warmup is even more important because cold starts can be expensive.
Scale workers the right way
Most production systems scale background workers horizontally.
Scale based on:
- Queue depth
- Job latency
- CPU usage
- Memory usage
- GPU usage
- Request rate
- Provider rate limits
Popular deployment options:
- Kubernetes deployments with autoscaling
- ECS or container apps
- Managed queue workers
- Serverless event workers for short tasks
Important scaling rule
Do not scale workers faster than your model provider or database can handle. Worker count should match downstream capacity.
Example production stack
A practical stack for many teams looks like this:
- API: FastAPI, Django, Flask, Express, or Rails
- Queue: Redis, SQS, RabbitMQ
- Workers: Celery, Sidekiq, BullMQ, or custom consumers
- Model access: OpenAI, Anthropic, Bedrock, local vLLM, TGI, or Ollama in controlled environments
- Storage: Postgres, S3, Redis cache, vector DB
- Monitoring: Prometheus, Grafana, Datadog, OpenTelemetry
- Deployment: Docker + Kubernetes, ECS, or managed container platforms
A simple implementation pattern
Here is a basic production flow you can adapt:
- Validate the request in the API
- Save the raw input and create a job record
- Enqueue a job with a unique ID
- Worker claims the job
- Worker marks status as running
- Worker calls the AI model or pipeline
- Worker stores output and updates status
- Worker emits logs, metrics, and traces
- UI polls or receives a callback
- Failed jobs move to retry or dead-letter handling
If the job is critical, persist each step so you can resume work after crashes.
Common mistakes to avoid
Running AI inference in the web request
This often causes timeouts and poor user experience.
Sharing one queue for everything
One slow job type can block all others.
Ignoring retries and duplicates
This leads to duplicate writes, duplicate emails, or repeated billing.
Not measuring token usage
Costs can grow silently.
Using a single worker type for CPU and GPU tasks
This wastes resources and hurts performance.
Skipping observability
Without logs and metrics, production issues are hard to diagnose.
When serverless workers are a good fit
Serverless background workers can work well if jobs are short and spiky.
Good fit:
- Small text transformations
- Light classification
- Event-triggered enrichment
- Occasional document processing
Less ideal:
- Long model warmup
- Large file processing
- GPU workloads
- High-throughput inference
- Tasks that need consistent low latency
If your AI jobs are frequent or heavy, dedicated worker services are usually more reliable.
Production checklist
Before launching, make sure you have:
- A queue system
- Idempotent job handlers
- Retries with backoff
- Dead-letter handling
- Job status storage
- Metrics and alerts
- Structured logs
- Traceability across services
- Cost monitoring
- Rate limiting and throttling
- Security controls for sensitive data
- A rollback plan for prompt or model changes
Bottom line
The best way to run background workers for AI tasks in production is to treat them like a real distributed system, not just a helper script. Put AI work behind a queue, make jobs idempotent, isolate worker types, add retries and dead-letter handling, monitor latency and cost, and scale based on real demand. That approach keeps your app fast, your AI pipeline reliable, and your production environment much easier to operate.
If you want, I can also turn this into:
- a Node.js example with BullMQ
- a Python example with Celery
- a Kubernetes deployment pattern
- or a serverless architecture for AI background jobs