---
title: "Deploy a BullMQ, Celery or Sidekiq worker with while.sh"
url: https://while.sh/en/guides/background-worker-queue/
author: "Aloïs Oddon, co-founder of Nextmap"
updated: 2026-11-02
---

# Run a background worker with BullMQ, Celery or Sidekiq, from your AI agent

Sending emails, running exports and heavy processing don't belong in your requests. Connected to while over MCP, your AI agent deploys the worker that handles them in the background, with its queue.

## Prerequisites

- An app that puts tasks in a queue: BullMQ, Celery, RQ or Sidekiq.
- An AI agent that works in a terminal: Claude Code, Codex, Cursor or Gemini CLI.

## Step 1: Give your agent these instructions

Open your agent in your app's folder, and paste these instructions into it:

```text titre="Instructions"
Connect to while with my account (while.sh/agents), then deploy my app.
```

Your agent adds while's MCP server itself. If it asks you to, restart it. On the first call to while, a page opens in your browser. In Claude Code, if it doesn't open, type /mcp, choose while, then Authenticate. On that page, choose "A new app", then click Authorize.

## Step 2: Open your app

Your agent gives you your app's address, for example `https://mon-appli.while.cloud`, over HTTPS.

## What your agent does

It adds the worker and its queue to while.yaml:

```yaml titre="while.yaml"
apiVersion: while/v1
project: mon-appli
services:
  - name: web
    port: 3000
  - name: worker
    type: worker
    command: [node, worker.js]
caches:
  - name: file
    durable: true
```

The worker runs nonstop, with no public address, and with the same code as your app. Its queue lives in a durable Redis-compatible cache: nothing is lost on restart. Its address, password included, arrives in `REDIS_URL`, as in this BullMQ worker (source 1):

```js titre="worker.js"
import { Worker } from 'bullmq';
import IORedis from 'ioredis';

const connection = new IORedis(process.env.REDIS_URL, { maxRetriesPerRequest: null });

new Worker('emails', async (job) => {
  await envoyerEmail(job.data);
}, { connection });
```

## Run a Celery worker

> You, to your agent: Add a Celery worker for the exports.

Your agent declares the worker with the command `celery -A monappli worker`, connected to the same cache: it gives `REDIS_URL` to Celery, with `broker=os.environ['REDIS_URL']`.

## See what your worker is doing

> You, to your agent: Why are the emails going out late?

Your agent reads the worker's logs in while, finds the task that is stuck and fixes it.

## Add memory

> You, to your agent: Give the exports worker more memory.

Your agent changes `resources` in while.yaml, and the worker restarts with it on the next deployment.

## Go back to the previous version

> You, to your agent: Go back to the previous version of the worker.

The previous version of the worker resumes in a few seconds. Your agent reads the error in the logs, fixes it and deploys again.

## Next steps

- [Run a scheduled job](/en/guides/run-cron-job/)
- [Add a Redis-compatible cache](/en/guides/add-redis-cache/)
- [Deploy a Ruby on Rails app](/en/guides/deploy-rails/)

## Sources

1. [BullMQ, workers](https://docs.bullmq.io/guide/workers), 2026-11-02

## Questions

### Does my worker run twice during an update?

No: a new version replaces the old one, and the two never run at the same time.

### Celery, RQ or Sidekiq?

All of them: the worker runs the command of your choice, with the same code as your app.

### What about a job that runs at a fixed time?

A scheduled job costs less: it only runs for as long as the work takes.

### Does my worker have a public address?

No, it runs without an address: no one can call it from outside.
