Skip to main content

A fast distributed task queue with a Rust core and a Python API, backed by Redis streams.

Project description

ArdiQ

PyPI version Python versions CI License: MIT


A fast distributed task queue with a Rust core and a clean Python API, backed by Redis streams.

ArdiQ runs the worker loop and all Redis I/O in Rust (via PyO3 + tokio); you write tasks in plain Python. The two meet at a single async callback, with the GIL held only for the microseconds it takes to start a task and read its result — so a single process handles high concurrency.

Features

  • 🦀 Rust core — the loop and Redis I/O run on tokio, off the GIL
  • Priority queues — higher-priority tasks are consumed first
  • Delayed & scheduled tasks (delay_ms / schedule_ms)
  • Cron & recurring tasks (@app.cron) — 5-field cron (UTC) or every= intervals
  • Automatic retries with quadratic backoff, configurable per task
  • Crash recovery — in-flight tasks of a dead worker are reclaimed (XAUTOCLAIM)
  • Results with TTL, plus task status (queued / running / complete / not_found)
  • Sync & async tasks — blocking sync functions run in a thread pool
  • CLI worker (ardiq run module:app) and burst mode (drain the queue and exit)

Performance

Because the worker loop and every Redis round-trip run in Rust — off the GIL — ArdiQ delivers top-tier throughput at a fraction of the memory of comparable Python task queues.

Benchmarked head-to-head against arq, Taskiq, Streaq, Celery and Dramatiq on the same machine (1,000 tasks, one worker, 10 concurrent):

Queue Throughput Memory
ArdiQ 🦀 top tier ~34 MB 🪶
Taskiq top tier ~95 MB
Streaq fast ~50 MB
arq fast ~30 MB
  • 🏆 Among the fastest async queues on both CPU- and I/O-bound workloads — effectively tied with the leader.
  • 🪶 Lightest in its class — roughly a third of the memory of the next-fastest queue, and the lowest footprint of any queue at its performance level.
  • 📈 Near the theoretical ceiling on I/O work — practically network-bound, with nothing lost to scheduling.
  • 🎯 Rock-steady — negligible variance run to run.

Throughput is shaped by hardware and workload, and the GIL caps in-process CPU work for every Python queue (ArdiQ included). The full, reproducible suite — with the honest caveats — lives in the benchmark repo.

When to use ArdiQ

Reach for ArdiQ when you want:

  • High concurrency on a small footprint — async-native, with the loop and Redis I/O in Rust, so one process does a lot without eating memory.
  • A modern, typed API@app.task, awaitable enqueue, Job handles, results and status built in.
  • Reliability out of the box — priorities, retries with backoff, delayed and scheduled tasks, and crash recovery via Redis consumer groups.
  • Redis you already run — no extra broker to operate.

Consider the alternatives when:

  • You need to saturate many CPU cores in one process — like every single-process Python queue, ArdiQ runs your task body under the GIL, so CPU-bound work is serial per worker (scale out with more workers). For heavy CPU fan-out, a prefork model (Celery, Dramatiq) can be simpler.
  • You need a large, battle-tested ecosystem today — Celery has years of integrations, schedulers, and dashboards. ArdiQ is young and moving fast.
  • You can't run Redis — ArdiQ is Redis-only by design.

ArdiQ sits alongside arq / Taskiq / Streaq as a modern async queue — its edge is the Rust core (memory and per-task overhead) and a batteries-included API.

Installation

$ pip install ardiq

The base install is the library only — a single runtime dependency (msgpack) — enough to define tasks, enqueue them, and run a worker from your own code (await app.run()). For the ardiq worker command, add the CLI extra:

$ pip install 'ardiq[cli]'

You also need a Redis server — the quickest way is Docker:

$ docker run -d --name ardiq-redis -p 6379:6379 redis

or install it from your package manager (or redis.io).

Building from source (if you want to hack on ArdiQ itself): you'll need Rust and uv. Clone the repo and run uv sync.

Quickstart

Define an app and some tasks (example.py):

from ardiq import Ardiq

app = Ardiq(redis_url="redis://localhost:6379", queue_name="example")


@app.task()
async def add(a: int, b: int) -> int:
    return a + b


@app.task(max_retries=3)
def slow_double(x: int) -> int:   # sync task — runs in a thread
    return x * 2

Start a worker:

$ ardiq run example:app

Enqueue tasks from anywhere and read their results:

import asyncio
from example import add


async def main():
    job = await add.enqueue(2, 3)        # returns a Job handle
    print(job.id)
    print(await job.status())            # 'queued' | 'running' | 'complete'
    print(await job.result(timeout=5))   # waits → TaskResult(success=True, value=5, tries=1)


asyncio.run(main())

Or run the whole thing in one process with python example.py, which enqueues a few tasks and processes them in burst mode.

Recurring tasks

Register a task to run on a schedule with @app.cron — either a standard 5-field cron expression (evaluated in UTC) or a fixed every= interval:

@app.cron("0 3 * * *")            # daily at 03:00 UTC
async def nightly_report():
    ...


@app.cron(every=30)               # every 30s — int/float seconds or a timedelta
async def heartbeat():
    ...

Recurring tasks fire while a worker is running, and each occurrence is an ordinary task with its own result, status, retries and timeout. The cron syntax is the common subset — *, lists ,, ranges a-b, and steps */n — at minute resolution; use every= for sub-minute schedules.

Configuration

Ardiq(...) accepts:

Option Default Description
redis_url redis://localhost:6379 Redis connection URL
queue_name "default" Logical queue (key namespace)
priorities ["default"] Priority names, lowest-first
concurrency 16 Max tasks running at once
prefetch concurrency * 2 Max tasks held in memory (drives backpressure)
idle_timeout_ms 60000 When an unrenewed in-flight task may be reclaimed
result_ttl_ms 300000 How long results live (0 drops, negative keeps forever)
burst False Exit once the queue drains
serializer / deserializer msgpack Wire codec; pass pickle.dumps/pickle.loads to send datetimes/objects
cron_poll_s 1.0 How often the worker restages due @app.cron occurrences

@app.task(...) accepts name, max_retries (default 3), backoff_ms, timeout (seconds), and priority. @app.cron(spec, *, every=…, …) takes those same per-task options plus the schedule. Use task.options(delay_ms=…, schedule_ms=…, priority=…, task_id=…).enqueue(...) for one-off overrides.

Logging

ardiq run configures Python's logging for the process (INFO by default, DEBUG with --verbose/-v) and also initializes the Rust core's own logging at the same level. Worker lifecycle (worker starting, worker stopped) logs at INFO; task lifecycle logs at DEBUG (task started, task succeeded) through WARN (task retry scheduled) and ERROR (task failed, task unknown). Task args, kwargs, and results are never logged.

Logging inside a task is just standard logging — it works the same for async tasks and for sync tasks run via asyncio.to_thread:

import logging

logger = logging.getLogger(__name__)


@app.task()
async def send_email(to: str) -> None:
    logger.info("sending email to %s", to)
    ...

If you embed Ardiq outside the ardiq CLI, call logging.basicConfig(...) yourself (see example.py).

Development

$ docker compose up -d      # Redis on localhost:6379
$ uv run pytest             # test suite (needs Redis)
$ uv run ruff check .       # lint
$ uv run ty check ardiq tests   # type-check

After changing the Rust core, rebuild with uv sync --reinstall-package ardiq.

License

MIT

Project details


Download files

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

Source Distribution

ardiq-0.2.2.tar.gz (31.5 kB view details)

Uploaded Source

Built Distributions

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

ardiq-0.2.2-cp39-abi3-win_amd64.whl (1.5 MB view details)

Uploaded CPython 3.9+Windows x86-64

ardiq-0.2.2-cp39-abi3-manylinux_2_17_x86_64.manylinux2014_x86_64.whl (1.8 MB view details)

Uploaded CPython 3.9+manylinux: glibc 2.17+ x86-64

ardiq-0.2.2-cp39-abi3-manylinux_2_17_aarch64.manylinux2014_aarch64.whl (1.8 MB view details)

Uploaded CPython 3.9+manylinux: glibc 2.17+ ARM64

ardiq-0.2.2-cp39-abi3-macosx_11_0_arm64.whl (1.6 MB view details)

Uploaded CPython 3.9+macOS 11.0+ ARM64

ardiq-0.2.2-cp39-abi3-macosx_10_12_x86_64.whl (1.7 MB view details)

Uploaded CPython 3.9+macOS 10.12+ x86-64

File details

Details for the file ardiq-0.2.2.tar.gz.

File metadata

  • Download URL: ardiq-0.2.2.tar.gz
  • Upload date:
  • Size: 31.5 kB
  • Tags: Source
  • Uploaded using Trusted Publishing? Yes
  • Uploaded via: twine/6.1.0 CPython/3.13.12

File hashes

Hashes for ardiq-0.2.2.tar.gz
Algorithm Hash digest
SHA256 1a8496236aa5e14d5d63af4f69e73c4fda16227be3dd4e26955dc8cc9037933c
MD5 ac0d66193460111c0a4f7a4beaa0b45f
BLAKE2b-256 d80b40cf46e88403eab39358699d17b35354b5e7d02cff9e3ec1fb27c04fb331

See more details on using hashes here.

Provenance

The following attestation bundles were made for ardiq-0.2.2.tar.gz:

Publisher: release.yml on 17tayyy/ardiq

Attestations: Values shown here reflect the state when the release was signed and may no longer be current.

File details

Details for the file ardiq-0.2.2-cp39-abi3-win_amd64.whl.

File metadata

  • Download URL: ardiq-0.2.2-cp39-abi3-win_amd64.whl
  • Upload date:
  • Size: 1.5 MB
  • Tags: CPython 3.9+, Windows x86-64
  • Uploaded using Trusted Publishing? Yes
  • Uploaded via: twine/6.1.0 CPython/3.13.12

File hashes

Hashes for ardiq-0.2.2-cp39-abi3-win_amd64.whl
Algorithm Hash digest
SHA256 11039f79624534549b19b0f83a91f7559818ec027fb5ae52a54c058664d31e71
MD5 1dd7e0543df710255c8096f5095e3fbd
BLAKE2b-256 3ca41f6684eaa34902f099f203d051cb15e5589d7acbccb23f87527c6255b5d7

See more details on using hashes here.

Provenance

The following attestation bundles were made for ardiq-0.2.2-cp39-abi3-win_amd64.whl:

Publisher: release.yml on 17tayyy/ardiq

Attestations: Values shown here reflect the state when the release was signed and may no longer be current.

File details

Details for the file ardiq-0.2.2-cp39-abi3-manylinux_2_17_x86_64.manylinux2014_x86_64.whl.

File metadata

File hashes

Hashes for ardiq-0.2.2-cp39-abi3-manylinux_2_17_x86_64.manylinux2014_x86_64.whl
Algorithm Hash digest
SHA256 bc8d9fc355394863ec6026ecdc515165b8c591ce2897ac28dd44230b38163231
MD5 63b3e4bccb14224369fd92867b851554
BLAKE2b-256 3943b128814633c621843f3b6aa383032e398dd3cb37771da9879d379ec45118

See more details on using hashes here.

Provenance

The following attestation bundles were made for ardiq-0.2.2-cp39-abi3-manylinux_2_17_x86_64.manylinux2014_x86_64.whl:

Publisher: release.yml on 17tayyy/ardiq

Attestations: Values shown here reflect the state when the release was signed and may no longer be current.

File details

Details for the file ardiq-0.2.2-cp39-abi3-manylinux_2_17_aarch64.manylinux2014_aarch64.whl.

File metadata

File hashes

Hashes for ardiq-0.2.2-cp39-abi3-manylinux_2_17_aarch64.manylinux2014_aarch64.whl
Algorithm Hash digest
SHA256 b659fd6c1a75f2d3fabf681cae2131c480c97b4897a86bb2e5eef5055d733a7a
MD5 4a080ae0df90e681106507b8dc479230
BLAKE2b-256 d5865af42497fe317c2ca6949111ea713c875b21569eee827fdcd7d26a72a2ba

See more details on using hashes here.

Provenance

The following attestation bundles were made for ardiq-0.2.2-cp39-abi3-manylinux_2_17_aarch64.manylinux2014_aarch64.whl:

Publisher: release.yml on 17tayyy/ardiq

Attestations: Values shown here reflect the state when the release was signed and may no longer be current.

File details

Details for the file ardiq-0.2.2-cp39-abi3-macosx_11_0_arm64.whl.

File metadata

  • Download URL: ardiq-0.2.2-cp39-abi3-macosx_11_0_arm64.whl
  • Upload date:
  • Size: 1.6 MB
  • Tags: CPython 3.9+, macOS 11.0+ ARM64
  • Uploaded using Trusted Publishing? Yes
  • Uploaded via: twine/6.1.0 CPython/3.13.12

File hashes

Hashes for ardiq-0.2.2-cp39-abi3-macosx_11_0_arm64.whl
Algorithm Hash digest
SHA256 98ff6d9326a9e8c3ddbcaea75d664759711b195919b5117833127df4ae544b5f
MD5 3456e005dcfb885ccc78bcf6b6a668b5
BLAKE2b-256 a2e72ac2700fbf06a8d626cebd223feffed9bb9990cbc5fe02c59c9dd1e51a8d

See more details on using hashes here.

Provenance

The following attestation bundles were made for ardiq-0.2.2-cp39-abi3-macosx_11_0_arm64.whl:

Publisher: release.yml on 17tayyy/ardiq

Attestations: Values shown here reflect the state when the release was signed and may no longer be current.

File details

Details for the file ardiq-0.2.2-cp39-abi3-macosx_10_12_x86_64.whl.

File metadata

File hashes

Hashes for ardiq-0.2.2-cp39-abi3-macosx_10_12_x86_64.whl
Algorithm Hash digest
SHA256 daa8105c7583aabf036b2e7bb40824dc47f86b5a96aaedb6e95f388803428dd3
MD5 ca7ca57661fe97c5ea79e5b6682f9d60
BLAKE2b-256 5639759b6af30ce5319a02c70bf54450919d970f4148dd813e5193e71dedca72

See more details on using hashes here.

Provenance

The following attestation bundles were made for ardiq-0.2.2-cp39-abi3-macosx_10_12_x86_64.whl:

Publisher: release.yml on 17tayyy/ardiq

Attestations: Values shown here reflect the state when the release was signed and may no longer be current.

Supported by

AWS Cloud computing and Security Sponsor Datadog Monitoring Depot Continuous Integration Fastly CDN Google Download Analytics Pingdom Monitoring Sentry Error logging StatusPage Status page