Skip to main content

z4j-scheduler

PyPI version Python License

The engine-agnostic dynamic scheduler for z4j.

One service drives Celery, RQ, Dramatiq, Huey, arq, and TaskIQ from a single dashboard. Schedules live in z4j's database, you edit them live without restarting anything, every change made through z4j is recorded in an HMAC-chained audit log, and importers + exporters keep the door open in either direction. This is the canonical scheduler when you want one place to manage cron / interval / one-shot / solar schedules across mixed engines.

Compatibility

Python 3.11+. PostgreSQL 17+ for shared-database HA (SQLite is supported for single-node brain deployments). The scheduler sends each prepared fire to the brain, which routes it to a connected Celery, RQ, Dramatiq, Huey, arq, or TaskIQ agent; engine packages do not need to be installed beside the scheduler service.

Full per-adapter matrix at https://z4j.dev/reference/compatibility/.

What makes z4j-scheduler different

z4j-scheduler is a deliberate alternative to in-language schedulers like celery-beat, rq-scheduler, and APScheduler. The differences that matter day to day:

  • Engine-agnostic. One scheduler service for every supported Python task engine. A project running Celery for legacy services and arq for a FastAPI rewrite uses the same scheduler for both, with one dashboard and one audit trail.
  • Live editing. Schedules live in the brain's database. Create, edit, pause, resume, rename, and delete from the dashboard or REST API without restarting the scheduler service.
  • HMAC-chained audit log. Every schedule mutation that goes through z4j records the actor, change, and time (plus the source IP for request-originated changes) in an HMAC-chained audit trail alongside the brain's other audit rows, and the database refuses a schedule change that arrives without a fresh revision and a matching change-log entry. That covers the dashboard, the API, config, and any adapter, including an older one. It does not cover a database role writing those tables directly, which can supply the revision and the change-log entry itself; guard those credentials accordingly.
  • HA-ready. Multiple scheduler instances can run against the same Postgres database. Depending on the configured backend, Postgres advisory locks elect one global leader or one leader per project; followers stay warm. Failover latency follows the configured leader heartbeat, and slots that age during a handoff are handled by the per-schedule catch-up policy.
  • Migration tooling. The CLI imports celery-beat (static and django-celery-beat), rq-scheduler, APScheduler SQLAlchemy jobstores, and system crontab. It exports reviewable Celery, RQ, APScheduler, or crontab configuration. Generated output is advisory and must be reviewed and tested against the target scheduler by the operator. This is not a lossless rollback: target formats cannot represent every z4j schedule kind or policy, and unsupported rows render as comments for manual handling.

What it ships

Capability Notes
Schedule kinds cron, interval, one-shot, solar (sunrise / sunset / dawn / dusk / noon / midnight at a given lat / lon)
Live editing dashboard and REST API require no restart; declarative config reconciles when a configured framework startup hook or helper/CLI invokes it
Engine fan-out Celery, RQ, Dramatiq, Huey, arq, TaskIQ
Importers celery / django-celery-beat / rq-scheduler / apscheduler / cron
Exporters celery / rq / apscheduler / cron; generated output is advisory, and target limitations can require manual handling
HA leader election Postgres advisory locks; global or per-project leadership, with warm followers
Audit log every mutation through z4j is HMAC-chained; the database refuses a schedule change with no matching change-log entry, though a role holding direct write access to those tables can supply both
Catch-up policy per-schedule: skip, fire one missed, fire all missed
Timezones IANA zones validated at the boundary; DST fall-back fold fixed (no double-fires); spring-forward gap handled
Trigger surface brain validates and dispatches operator-triggered fires directly; manual fires do not advance the cadence cursor

Install

Standalone (recommended for production):

pip install z4j-scheduler
export Z4J_SCHEDULER_BRAIN_GRPC_URL=brain.internal:7701
export Z4J_SCHEDULER_BRAIN_REST_URL=https://brain.internal
export Z4J_SCHEDULER_TLS_CERT=/etc/z4j/scheduler.crt
export Z4J_SCHEDULER_TLS_KEY=/etc/z4j/scheduler.key
export Z4J_SCHEDULER_TLS_CA=/etc/z4j/ca.crt
export Z4J_SCHEDULER_BIND_HOST=127.0.0.1
z4j-scheduler serve

On the brain host, install z4j[scheduler-grpc] and enable the brain's mTLS scheduler listener. A separate scheduler installation does not add the gRPC runtime to the brain environment. The loopback operational bind above keeps /metrics local to that host; a non-loopback production bind also requires a metrics auth token or explicitly disabled metrics.

Embedded inside z4j (recommended for homelab and small teams):

pip install z4j z4j-scheduler
# then enable in brain settings: Z4J_EMBEDDED_SCHEDULER=true

With the flag on, the brain spawns and supervises a z4j-scheduler serve subprocess for you, no separate deployment unit to manage.

Migrate existing schedules in:

pip install 'z4j-scheduler[celery-import]'
z4j-scheduler import \
  --from celery \
  --celery-app myapp.celery:app \
  --project myproject \
  --brain-url https://brain.example.com \
  --api-token "$Z4J_SCHEDULER_BRAIN_API_TOKEN"

The other importer subcommands follow the same shape (--from rq, --from apscheduler, --from django-celery-beat, etc.). Add --dry-run to print the parsed schedules as JSONL for review instead of writing them to the brain. --verify also implies dry-run; a normal run with neither flag pushes the imported schedules immediately.

When to choose z4j-scheduler

You probably want it if:

  • You run more than one Python task engine and want one schedule surface across all of them.
  • An auditor or a security review asks who paused the nightly billing job last Tuesday and you don't have a clean answer.
  • You want to edit schedules without restarting a static-config scheduler.
  • You want HA scheduling without standing up a second control plane.
  • You're considering a one-time migration from celery-beat / rq-scheduler / APScheduler and want reviewable import and export tooling while accepting the target format's limitations.

You probably don't need it if:

  • You run a single engine (typically Celery), have no compliance pressure, and the in-language scheduler already meets your needs. Stay where you are; we ship z4j-celerybeat / z4j-rqscheduler / z4j-apscheduler as adapters that surface those schedules in the z4j dashboard and expose the controls each backend supports, without replacing the native scheduler or taking ownership of its cadence.

Documentation

Full docs at z4j.dev/scheduler/. The migration guide at z4j.dev/scheduler/migrating-from-celery-beat/ walks the importer + dashboard verification path step by step.

License

Apache-2.0, see LICENSE. z4j-scheduler is independently installable from the AGPL-licensed z4j server distribution; consult the license terms for the obligations that apply to your deployment. The accepted Z4J_SCHEDULER_PRO_LICENSE_KEY setting is a reserved, inert compatibility field; setting it enables no feature.

Links

Download files

Download the file for your platform. If you're not sure which to choose, learn more about installing packages.

Source Distribution

z4j_scheduler-1.9.0.tar.gz (211.2 kB view details)

Uploaded Source

Built Distribution

If you're not sure about the file name format, learn more about wheel file names.

z4j_scheduler-1.9.0-py3-none-any.whl (253.5 kB view details)

Uploaded Python 3

File details

Details for the file z4j_scheduler-1.9.0.tar.gz.

File metadata

  • Download URL: z4j_scheduler-1.9.0.tar.gz
  • Upload date:
  • Size: 211.2 kB
  • Tags: Source
  • Uploaded using Trusted Publishing? No
  • Uploaded via: twine/7.0.0 CPython/3.14.7

File hashes

Hashes for z4j_scheduler-1.9.0.tar.gz
Algorithm Hash digest
SHA256 6492c9467ae65198bf89fdd5b72edafea42ccf6bf785d7fd2a3205bf8d126c62
MD5 8dd2efd27218334d5646b21c183b1886
BLAKE2b-256 5b77b0b50786f66ce33cd27a46634b6a8f1e0e589166b9d0efd8207a33d5c2fd

See more details on using hashes here.

File details

Details for the file z4j_scheduler-1.9.0-py3-none-any.whl.

File metadata

  • Download URL: z4j_scheduler-1.9.0-py3-none-any.whl
  • Upload date:
  • Size: 253.5 kB
  • Tags: Python 3
  • Uploaded using Trusted Publishing? No
  • Uploaded via: twine/7.0.0 CPython/3.14.7

File hashes

Hashes for z4j_scheduler-1.9.0-py3-none-any.whl
Algorithm Hash digest
SHA256 a9164dd4a8aac55ed2b33eb015a13bb18c7b65e4fdc25becd2f5e5e748b88036
MD5 682655f6b03bd4cf60189564b7b348c0
BLAKE2b-256 28b97573023da7729441ad42ecf7f97915151d6b75c9f487e351c0a054073e0f

See more details on using hashes here.

Release history Release notifications | RSS feed

1.10.0

2 files

1.9.1

2 files

This release

1.9.0 This release

2 files

1.8.0

2 files

1.7.0

2 files

1.6.7

2 files

1.6.5

2 files

1.6.0

2 files

1.5.0

2 files

1.4.0

2 files

1.3.0

2 files

1.1.2

2 files

1.1.0

2 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