Keyboard shortcuts

Press ← or → to navigate between chapters

Press S or / to search in the book

Press ? to show this help

Press Esc to hide this help

Introduction

cronoq is an elastic, priority-aware task scheduler. It decides when each piece of work runs, in what order, and how much capacity a pool of workers needs. Where the work runs is up to you: async functions in your Rust process, Python coroutines, or remote workers written in any language and connected over gRPC.

            submit                 dispatch                  execute
 your code ─────────▶  cronoq  ─────────────▶  executor / remote worker
     ▲                (ordering, limits,             │
     └──── result ───  reservations, scaling) ◀──────┘ outcome

What it does

CapabilityWhat you get
Priorities with agingFour classes (critical, high, normal, low), FIFO within a class, and aging so that a stream of normal work cannot starve low-priority work forever.
DeadlinesTasks with a deadline gain urgency smoothly as their latest start time approaches, and are ordered earliest-deadline-first within their class.
Fixed starts and cronWork that must start at a given time reserves capacity in advance and gets a worker held for it, with a policy for what to do if it still misses its slot.
DependenciesDAGs by task id or key, with on_success, on_failure and on_complete edges. Batches are admitted atomically.
ReliabilityLeases with heartbeats, per-attempt timeouts, retries with exponential backoff and retry_after, dead-lettering, cancellation, idempotent keys.
Shared resourcesSemaphores and token buckets shared across pools: API rate limits, GPU slots, database connections.
ElasticityEach pool computes how many workers it needs from arrival rate, backlog, wait-time SLOs and upcoming reservations, and asks a pluggable scaler for them.
BackpressureBounded queues that make submitters wait, reject, or shed lower-priority work.
Durability and HAPostgres and SQLite stores with leader election and fencing; standby servers take over and resume every accepted task.
ObservabilityOpenTelemetry metrics and trace propagation, Prometheus /metrics, and windowed quality metrics such as priority adherence and fixed-start hit rate.

Three ways to use it

  1. Rust library (cronoq crate): embed the scheduler in a tokio application. Payloads are plain Rust values; nothing is serialized. See the Rust quickstart.
  2. Python package (pip install cronoq): the same engine with asyncio bindings. Payloads are Python objects. See the Python quickstart.
  3. Server (cronoq-server): a standalone service with a gRPC and HTTP/JSON API. Clients in any language submit work and remote workers lease it, with SDKs for Rust, Python, Go and TypeScript. See the Server quickstart.

All three share one engine, so the scheduling rules and metrics are the same everywhere. The Rust library exposes a few engine settings, such as the priority and urgency parameters, that the Python package and the server leave at their defaults.

How to read this book