Prerequisites
- Completed Your first app — you have a working project with
src/worker.ts. - Read ExuluQueues — introduction and ExuluQueues — configuration.
- Redis running and reachable (set
REDIS_HOST+REDIS_PORT).
ExuluQueues requires an Enterprise Edition license. register() throws immediately without a valid EXULU_ENTERPRISE_LICENSE environment variable.What you will build
- A sized embedder queue for a 2 M TPM embedding provider.
- A processor queue for document conversion jobs.
- A worker process scoped to only the embedder queue (so you can scale embedder workers independently).
1
Understand the sizing formula
The Example — a provider with a 2 M TPM quota embedding 1 024-token chunks:For For
ratelimit parameter limits how many jobs a single worker process dispatches per second. For embedding queues, the right value comes from your provider’s tokens-per-minute (TPM) quota:concurrency.queue, pick a number that represents the burst depth you want in Redis. A conservative starting point is ratelimit × 2 (enough to keep the queue fed):concurrency.worker, use the number of parallel I/O operations you want per process. Embedding calls are network-bound, so 5–10 is typical:2
Register the queues
Register all queues in Pass the queue to the context by calling
src/contexts/index.ts (or a dedicated src/queues.ts file). Queues must be registered before the context or eval that references them is constructed:src/queues.ts
.use():src/contexts/index.ts
.use() connects to Redis lazily on first await — the call itself is synchronous and returns a Promise<ExuluQueueConfig>. Passing the promise (not the awaited value) to the context lets IMP wire it up when the worker starts.3
Scope a worker to specific queues
By default, Add corresponding scripts to In your tsup config, add the processor worker as an entry:
app.bullmq.workers.create() starts workers for every registered queue. For production deployments, you often want separate containers for separate queue types — for example, high-memory document processors on beefy nodes and many small embedder workers on lighter ones.Pass queue names to workers.create() to restrict processing to a subset:src/worker.ts (embedder worker)
src/worker-processor.ts (processor worker)
package.json:tsup.config.ts
4
Memory guidance
PDF processing and embedding generation both use significant memory. As a starting point:
Document processing workers that load large PDFs or run OCR models can use 4–8 GB. Allocate accordingly in your container scheduler. See Operations for container sizing recommendations.Set
concurrency.worker: 1 for document processing workers if memory is constrained — running two large-PDF jobs in parallel doubles peak usage.5
Verify queue health
After starting your worker, registered queue names appear in the IMP admin interface under Build → Knowledge → [context] → Pipeline → [stage] → Jobs. You can also inspect queue depths, drain queues, and retry failed jobs from there.Every registered queue name is injected into the GraphQL
QueueEnum at boot, making queue state queryable via the platform’s API without additional configuration.What you built
- A sized embedder queue based on a TPM quota formula.
- Separate queues for embedding, processing, and sync.
- A worker entry point scoped to a single queue type, ready for independent horizontal scaling.
Next steps
ExuluQueues — configuration
Every register() parameter, the ExuluQueueConfig shape, and rate-limit sizing examples.
Operations
Container sizing, memory guidance, and production deployment patterns.
Custom processors
Attach a processor queue to a context and configure generateEmbeddings.