Live demo · Documentation · Website · Source · Changelog
z4j is the open-source control plane for Python task queues. One dashboard, one API and one audit trail for the task engines you already run: Celery, RQ, Dramatiq, Huey, arq and taskiq, side by side in the same project. An agent per layer of your stack streams every task, worker, queue and schedule event to a server you host, and carries operator actions back. Self-hosted. No telemetry. Nothing to rewrite.
pip install z4j
z4j serveOpen http://localhost:7700. First boot mints the secrets, runs the migrations and prints a one-time setup URL for the first admin. SQLite and the dashboard are bundled in the wheel; no database server and no npm install. For Docker, and for PostgreSQL when you want replicas, partitioned history and full-text search, see the install guide. Switching the database backend later does not move your data; the guide says exactly what does and does not carry over.
Running containers? The signed multi-arch z4jdev/z4j image ships with
Compose stacks for SQLite and PostgreSQL
(Docker guide), and the Helm chart
installs it on Kubernetes
(Kubernetes guide):
helm install z4j oci://ghcr.io/z4jdev/charts/z4j --namespace z4j --create-namespace| One project can run Celery, RQ and arq side by side. z4j renders the right badges per task, routes each action to the right adapter and keeps the audit log uniform. | Retry, cancel, bulk retry, purge, requeue dead-letter, restart worker, schedule CRUD and manual trigger, each run only where the connected adapter advertises it; z4j refuses the rest instead of faking them. Six engines do not have six identical feature sets, and the dashboard does not pretend they do. |
| The same exception across runs, and across engines, collapses into one issue with an occurrence count and an open or recovered state. | Per-project rules that notify, retry or cancel on a task or scheduler trigger, each with a circuit breaker, a kill switch and a dry-run mode. |
Every privileged action lands on an HMAC-chained log with issuer,
target, source IP, timestamp and result; z4j audit verify
checks the chain offline. The threat model, and the boundary the chain
does not cover, are published in the docs.
|
Four project-scoped roles (viewer, auditor, operator, admin), opt-in TOTP MFA with recovery codes, Argon2id passwords, signed session cookies, CSRF tokens and scoped API keys. |
| A background worker checks task state against the engine's own view where the engine exposes one, so a worker killed mid-task does not leave rows stuck on "running". | Email, Slack, Microsoft Teams, PagerDuty, Discord, Telegram and webhooks, with severity-aware subscriptions, cooldown and mute. |
|
|
|
|
demo.z4j.com is the dashboard running in your browser against sample data. One click on the pre-filled login lands you in a populated control plane with four sample projects, including a Django + Celery project with a live incident (a failing schedule, an alert firing, a worker offline) and a mixed-engine project driven by z4j-scheduler. It is a navigable preview, not a sandbox: mutations are blocked, no real backend is connected, and a refresh resets it.
z4j is the main application: server, dashboard, REST API, rule engine, audit log. One deployment per environment: a single process on SQLite, several worker processes or replicas on PostgreSQL. Agents connect outbound over an HMAC-signed WebSocket; the dashboard surfaces every task, worker, queue and schedule event and exposes the operator controls. Agents initiate every connection, so z4j never needs a route into your application network.
pip install z4j # SQLite, single process
pip install 'z4j[postgres]' # PostgreSQL driver for a replicated install
z4j serveSix Python task engines, all first-class. Mix them within a project.
| Engine | Adapter | Native scheduler companion | Notes |
|---|---|---|---|
| Celery | z4j-celery | z4j-celerybeat | Widest coverage: pool restart through Celery's own control channel, per-worker task rate limits. |
| RQ | z4j-rq | z4j-rqscheduler | Redis-backed; Django and Flask both first-class. |
| Dramatiq | z4j-dramatiq | (no upstream scheduler; use z4j-scheduler) | Middleware-based capture, no decorator changes to your actors. |
| Huey | z4j-huey | z4j-hueyperiodic | Huey 2.4 and later, on Huey 2 and Huey 3. |
| arq | z4j-arq | z4j-arqcron | Async-native; the common pairing with FastAPI. |
| taskiq | z4j-taskiq | z4j-taskiqscheduler | Async-native; middleware hooks. |
Applications that schedule with APScheduler use z4j-apscheduler.
Each adapter streams task lifecycle events to z4j and accepts operator actions back over the same WebSocket. All Apache-2.0. The exact action matrix per engine is on z4j.com.
The native scheduler integrations surface schedules from your existing scheduler so you can see them on the dashboard alongside tasks. Supported producers can expose dashboard create, edit, pause, resume, delete and manual-run controls alongside their observed schedules. Each control requires the producer setup documented by its adapter and its advertised capability; the native scheduler continues to execute the schedules. Code-defined sources use durable overrides rather than rewriting application files.
z4j-scheduler is z4j's own scheduler. Worth a closer look if you run more than one engine, want to edit schedules without a daemon restart, or need a record of who changed what.
- Engine-agnostic. One process drives all six engines. A project running Celery for older services and arq for a FastAPI rewrite uses one scheduler for both.
- Live editing. Schedules live in z4j's database. Create, edit, pause, resume and delete from the dashboard, declarative config or the REST API. No daemon restart.
- Audited. Every schedule change (who, what, when, from where) lands on the same HMAC-chained log as z4j's other privileged actions.
- Leader election. Multiple instances against one PostgreSQL database race for an advisory lock; only the leader ticks, followers stay warm. Takeover has no fixed response-time promise, and HA does not make task execution exactly-once.
- Catch-up you choose. After an outage each schedule decides for itself: skip what it missed, fire one, or fire every slot it owes.
- Importers and advisory exports. Import from celery-beat, django-celery-beat, rq-scheduler, APScheduler jobstores, system cron, Huey periodic tasks, arq cron jobs or taskiq schedule labels, with a diff you can verify before cutover. Exports for Celery, RQ, APScheduler, cron, Huey, arq and taskiq are advisory: you review and apply the generated file yourself. Dramatiq has no native scheduler to import from or export to.
- Cron, interval, one-shot and solar triggers. IANA zones are validated; during a fall-back an ambiguous wall-clock slot is two distinct instants and z4j fires once at each.
pip install 'z4j-scheduler[celery-import]'
z4j-scheduler import --from celery --celery-app myapp.celery:app --project myproject
# pass the brain URL with --brain-url (default http://localhost:7700); the
# token comes from --api-token or Z4J_SCHEDULER_BRAIN_API_TOKENFull comparison with celery-beat, django-celery-beat, rq-scheduler, APScheduler and cron, including where those remain the right choice: docs.z4j.com/schedulers/z4j-scheduler/.
One package per web framework. Each adapter registers the engines whose native handles you configure (Django discovers a configured Celery app; Flask and FastAPI take the engine handles you configure or pass), so cross-stack combinations such as Flask + RQ or FastAPI + arq are supported.
| Package | What it is |
|---|---|
| z4j-django | An AppConfig integration; the agent starts when Django boots. |
| z4j-flask | The Flask extension pattern, initialised on your app. |
| z4j-fastapi | A lifespan integration for async stacks. |
| z4j-bare | The framework-free agent runtime for plain scripts, worker processes and custom services. |
| z4j-core | The shared SDK used by every agent and by the brain. Protocols, domain models, redaction, the signed envelope. No framework imports. |
| z4j | The flagship distribution. The brain, plus an extras catalogue for pulling in adapters: pip install 'z4j[django,celery]' resolves a coherent stack in one command, with version floors that keep every package on one line. |
Quickstarts for each: https://docs.z4j.com/getting-started/install/.
- Self-hosted, no telemetry. z4j runs on infrastructure you control and sends no unsolicited vendor telemetry. Optional Sentry and OpenTelemetry exporters send data only when an operator installs and configures them.
- Verifiable audit trail. The HMAC-chained audit log, the threat model and the boundary the chain does not cover are documented in the threat model.
- Release integrity. Every PyPI release of every package has a
CycloneDX SBOM attached to its GitHub Release. The
z4jdev/z4jimage is signed keylessly with cosign and carries build provenance and an SPDX SBOM attestation, and each published Helm chart digest is signed. The verify commands are in the disclosure policy. - Reporting a vulnerability. Email
security@z4j.com; the same policy page covers scope, safe harbor and the response timeline.
Split on purpose, not by accident.
- z4j (the central process you run in your infrastructure) is
AGPL-3.0-or-later.
You can self-host, modify and redistribute. If you run a modified copy
as a network service, publish your modifications under the same
license. If that is incompatible with your policy, a commercial license
is available:
licensing@z4j.com. - All agent and scheduler packages (engine adapters, framework integrations, foundations and z4j-scheduler) are Apache-2.0. Integrating z4j into a proprietary application does not subject your application to the AGPL.
The ecosystem ships 19 active PyPI packages cross-versioned to one
release line, plus the frozen z4j-brain compatibility shim, which stays
at its legacy version and is not part of the release wave. Floors in
every package's pyproject keep mixed installs coherent. The badge at the
top of this page shows the current release; the release history is at
docs.z4j.com/reference/changelog/.