Skip to main content

Celery Board

A dashboard for Celery, built on Flower and inspired by bull-board.

It keeps Flower's core as it is: event capture, worker inspection, task search and Prometheus metrics. On top of that it puts a new UI, which you can serve with Tornado, Starlette/FastAPI or aiohttp.

Overview

Failed tasks Worker
Failed tasks Worker

Features

  • Tasks: bull-board style cards for every state: pending, received, started, retry, succeeded, failed, revoked and rejected. Each card has a timeline, arguments, result, traceback and routing details. Filter by task type and worker, or search with Flower's query syntax, like kwargs:user_id=42 or name:invoice AND state:FAILURE.
  • Actions:
    • Retry a task: it's sent again with the arguments Celery recorded, and you check them first.
    • Revoke a waiting task, terminate a running one, or remove a finished one from the board.
    • Send any task.
    • Revoke all or clean all the tasks you're looking at.
  • Workers: status, load, pool and queues, plus their active, reserved and scheduled tasks and registered tasks. Restart, grow or shrink the pool, start or stop consuming from a queue, or shut a worker down.
  • Queues: messages waiting in the broker (Redis or RabbitMQ), the workers consuming each queue, a warning for queues nobody consumes, and purge.
  • Periodic tasks: your beat_schedule, with each task's next run and a button to run it now.
  • Settings: light and dark themes in Flower's green, adjustable refresh, relative or absolute times, and local or UTC.
  • Operations: read-only mode, basic auth, and Prometheus metrics at /metrics.
  • No build step: Preact + htm, and everything ships with the package, fonts included, so it works offline.

Install

pip install celery-board                # runs on Tornado, like Flower
pip install "celery-board[starlette]"   # to mount it in Starlette or FastAPI, or --server starlette
pip install "celery-board[aiohttp]"     # to add it to aiohttp, or --server aiohttp

Python 3.10 or newer. Celery Board depends on flower>=2.2,<2.3, because it uses Flower's internals.

Run it

celery -A proj board
celery -A proj board --port 8080 --url-prefix /board --basic-auth admin:secret
celery -A proj board --server starlette     # or aiohttp

Then open http://localhost:5555. python -m celery_board -A proj board does the same.

Option Default
--address, --port 0.0.0.0, 5555 Where to listen.
--url-prefix Serve the board under a path, like /board.
--server tornado tornado, aiohttp or starlette (on uvicorn).
--basic-auth user:password, comma separated for several.
--read-only Hide and reject every action.
--max-tasks, --max-workers 100000, 5000 How many tasks and workers to keep in memory.
--persistent, --db off, celery-board Keep tasks across restarts in a file, saved on shutdown.
--state-save-interval 0 With --persistent, also save every this many milliseconds.
--broker-api RabbitMQ's management API, for queue lengths, like http://guest:guest@localhost:15672/api/.
--inspect-timeout 1000 Worker inspection timeout, in milliseconds.
--no-enable-events Don't ask workers to send events every 5 seconds.

The options work like Flower's options of the same name. Each one can also come from a CELERY_BOARD_* environment variable, like CELERY_BOARD_BASIC_AUTH.

Or mount it in your app

Each adapter takes your Celery app and the same options as keyword arguments, like read_only=True or basic_auth="admin:secret". You can also pass it a celery_board.Board.

Starlette / FastAPI

from celery_board.starlette import create_app

app.mount("/board", create_app(celery_app))

Starlette doesn't run a mounted app's lifespan, so the board starts capturing events with its first request. To start it along with your app, run its lifespan from yours:

board = create_app(celery_app)

@asynccontextmanager
async def lifespan(app):
    async with board.router.lifespan_context(board):
        yield

app = FastAPI(lifespan=lifespan)
app.mount("/board", board)

aiohttp

from celery_board.aiohttp import create_app

app.add_subapp("/board", create_app(celery_app))

Tornado

from celery_board.tornado import create_app, handlers

create_app(celery_app, url_prefix="/board").listen(5555)
# or, in your own app:
Application(handlers(celery_app, "/board") + your_handlers)

Tornado has no startup hook, so the board starts with its first request. You can also call Board.start() once the IOLoop runs.

Serve the board from one process. Each process captures events and keeps its own copy of the tasks.

Security

  • Basic auth: --basic-auth (or basic_auth=) protects the page and the API. As in Flower, /healthcheck and /metrics stay open for probes and Prometheus.
  • Your app's auth: mounted in your app, the board also sits behind your app's authentication.
  • Read-only: --read-only hides every action, and the API refuses them.
  • Cross-site writes: the board refuses writes from other sites (it checks Sec-Fetch-Site and Origin, like Flower), so a page elsewhere can't act through a logged-in browser.
  • Framing: pages can't be framed by other sites.
  • Task data: arguments, results and tracebacks show as your workers report them. To keep secrets out, send tasks with Celery's argsrepr and kwargsrepr.

How it works

Celery Board depends on Flower and uses its core as it is:

  • flower.events captures worker events in a thread. It keeps tasks and workers in memory, up to max_tasks, updates the Prometheus metrics, and with persistent saves them to a file.
  • flower.inspector asks workers for their stats, queues and task lists.
  • flower.utils.search indexes tasks for filtering, search and counts.
  • flower.utils.broker reads queue lengths from Redis or RabbitMQ.

On top of that:

  • celery_board.board holds the dashboard's queries and actions.
  • celery_board.web answers HTTP requests without depending on a framework.
  • The adapters: celery_board.tornado, .starlette and .aiohttp only translate requests and responses.

Good to know:

  • The board knows the tasks it has seen since it started, or since its last save with --persistent. It keeps the latest max_tasks.
  • Retry sends a new task with the arguments Celery recorded in its events. Those are reprs: cut at 1024 characters, and replaced by argsrepr when a task sets one. So the board shows them as JSON for you to check before sending. When they aren't plain values, you fill them in.
  • Worker details, like queues and task lists, refresh every minute, and every few seconds on a worker's page.

API

Method Path
GET /api/summary Counts per state and task type, and workers.
GET /api/tasks?state=&name=&worker=&search=&offset=&limit= Tasks, newest first, with counts per state.
POST /api/tasks Send a task: {"name", "args", "kwargs", "options"}.
GET /api/tasks/{id} One task.
POST /api/tasks/{id}/{action} revoke, terminate (optionally {"signal"}), remove.
POST /api/bulk/{action} revoke or clean the tasks matching {"state", "name", "worker", "search"}.
GET /api/registered Task names, for sending.
GET /api/workers Workers.
GET /api/workers/{name} One worker, with its inspection.
POST /api/workers/{name}/{action} shutdown, pool-restart, pool-grow or pool-shrink ({"n"}), add-consumer or cancel-consumer ({"queue"}).
GET /api/queues Queues, with waiting messages and consumers.
POST /api/queues/{name}/purge Delete a queue's waiting messages.
GET /api/periodic The beat_schedule.
POST /api/periodic/{name}/run Send a periodic task now.
GET /healthcheck, /metrics As in Flower.

Coming from Flower

  • The same core: Celery Board runs Flower's own event capture and inspection, so it sees your cluster the way Flower does.
  • The same port and options: it takes Flower's port and most of its options, and it serves the same flower_* Prometheus metrics.
  • Not included: Flower's OAuth login (put the board behind your own auth or proxy), and Flower's REST API paths, which the board's API above replaces. Autoscale, rate limits and time limits aren't in the UI.

Development

python -m venv .venv && .venv/bin/pip install -e ".[dev]"
redis-server --daemonize yes
.venv/bin/pytest                    # the end-to-end test uses redis://localhost:6379/15, or CELERY_BOARD_TEST_REDIS
.venv/bin/python examples/demo.py   # two workers, the board and some traffic, at http://localhost:5555

Credits

Built by rkwap. Celery Board stands on the shoulders of:

Celery Board is not affiliated with or endorsed by the Flower or Celery projects.

License

BSD 3-Clause, like Celery and Flower.

Metadata

Release files for celery-board 0.1.0

For a detailed explanation of source distributions (sdists) and built distributions (wheels), please see the package formats documentation.

Source distribution (sdist)

Source distribution for celery-board 0.1.0
File Size Uploaded
celery_board-0.1.0.tar.gz 189.6 kB Details

Built distribution (wheel)

Table of built distributions (wheels) for celery-board 0.1.0
File Interpreter ABI Platform
celery_board-0.1.0-py3-none-any.whl Python 3 none any Details

Total release size: 371.4 kB

Release files / celery_board-0.1.0.tar.gz

Download URL celery_board-0.1.0.tar.gz
Size 189.6 kB
Tags Source
SHA-256 checksum
How to use checksums
a4f737ad8b6cadf702ef88b18958015b79c91e7fcfbabea38df749168bca2353
BLAKE2b-256 checksum
How to use checksums
aacd47246d21625bcc73d699cf47fe17f55c74aedd473ff3aa4d109a0d962e8f
Upload date
Uploaded using Trusted Publishing?
What is trusted publishing?
Yes
Uploaded via twine/7.0.0 CPython/3.13.14

Provenance

Provenance describes where a file came from. On PyPI, provenance is shared via attestations, which provide a verifiable record of the build or publishing details. View details, limitations and caveats.

PyPI Publish Attestation

PyPI verified that this artifact, at this checksum, originated from the publisher listed below.

Signed by GitHub Actions, verified by PyPI on Sep 28, 2026.

Transparency log

Release files / celery_board-0.1.0-py3-none-any.whl

Download URL celery_board-0.1.0-py3-none-any.whl
Size 181.8 kB
Tags Python 3
SHA-256 checksum
How to use checksums
b4d63834fc9ce7ae28118f6d372b99cd34bdfd1e151f00e2ebb1342eb47f3783
BLAKE2b-256 checksum
How to use checksums
e35162b4d2415d2fc1ecff7e50b20a15630776105b7fd37b75f3fd450fe0dfcc
Upload date
Uploaded using Trusted Publishing?
What is trusted publishing?
Yes
Uploaded via twine/7.0.0 CPython/3.13.14

Provenance

Provenance describes where a file came from. On PyPI, provenance is shared via attestations, which provide a verifiable record of the build or publishing details. View details, limitations and caveats.

PyPI Publish Attestation

PyPI verified that this artifact, at this checksum, originated from the publisher listed below.

Signed by GitHub Actions, verified by PyPI on Sep 28, 2026.

Transparency log

Release history Release notifications | RSS feed

This release

0.1.0 This release

2 release files

Anthropic, PBC Visionary sponsor Bloomberg Visionary sponsor Hudson River Trading Visionary sponsor Meta Visionary sponsor NVIDIA Visionary sponsor Microsoft Sustainability sponsor Depot Continuous Integration AWS Cloud computing and Security Sponsor Datadog Monitoring Fastly CDN Google Download Analytics Sentry Error logging StatusPage Status page