Skip to content

jotarios/chasquimq

Repository files navigation

ChasquiMQ

ChasquiMQ

The fastest open-source message broker for Redis. Rust-native engine, MessagePack payloads, aggressive pipelining. Native Node.js and Python bindings — handlers run where you write them, the engine pulls jobs.

crates.io npm PyPI CI MIT License

Website · Getting started · API reference · Guides · Concepts

Status: 1.0 shipped; 1.x cloud-Redis polish landed (TLS, connection tuning, rotating-token auth). The public API is stable in shape.

Named after the chasquis — the relay runners of the Inca road system who carried messages across the Andes.

Headline numbers

Apple M3, Redis 8.6 (loopback Docker), bullmq-bench vs chasquimq-bench on the same host. Measured 2026-05-07 under load avg ~1.8–4.3.

Scenario BullMQ 5.76.4 ChasquiMQ Ratio
queue-add-bulk (50, tiny payload) 54,455 jobs/s 188,775 jobs/s 3.47×
worker-concurrent (100 workers) 45,643 jobs/s 111,968 jobs/s 2.45×
queue-add (single, 10×10 payload) 13,245 jobs/s 15,366 jobs/s 1.16×

worker-concurrent is the most CPU-contention-sensitive scenario in the suite; on a quiet host (load < 1) ChasquiMQ reaches ~419k jobs/s for an 8.78× ratio. See benchmarks/ for full methodology, distribution stats, and the canonical quiet-host run.

Latency, low-rate dispatch: end-to-end p50 ~1 ms, p99.9 < 3 ms; engine-side handler dispatch p99.9 ~13 µs on a no-op handler. Same contended Mac. Methodology and caveats in benchmarks/latency-1.x.md.

Why it's fast

  • Redis Streams over LPUSH/BRPOP. Consumer groups, idle-claim recovery, and atomic ack/delete primitives — not LIST polling.
  • MessagePack payloads via rmp-serde. Binary, smaller, faster to encode than JSON on every hop.
  • Batched, pipelined XACK. Acks accumulate in a bounded channel and flush as a single round trip — the silent killer in naive Streams consumers.
  • XACKDEL (Redis 8.2) — atomic ack-and-delete, no ack-then-delete dance.
  • Atomic DLQ relocation. Routing a poisoned entry into the DLQ is one Lua script (ack-gate then re-enqueue), so a crash can't leave it both in the DLQ and pending — no duplicate on the next claim.
  • IDMP idempotent XADD (Redis 8.6) — producer retries after network blips don't double-publish; also belt-and-suspenders on the DLQ relocate.
  • Tokio multi-receiver dispatch. Per-job work stays off the reader's hot path; DLQ moves run on a dedicated relocator task.

Anti-patterns avoided: blocking Lua scripts, JSON payloads, per-job round trips.

Quickstart — Rust

chasquimq on crates.io · docs.rs. Requires Rust 1.85+ (2024 edition) and Redis 8.6+.

docker run -d --name chasquimq-redis -p 6379:6379 redis:8.6
cargo add chasquimq tokio --features tokio/macros,tokio/rt-multi-thread
use chasquimq::{Producer, Consumer, ProducerConfig, ConsumerConfig, HandlerError};
use serde::{Serialize, Deserialize};
use tokio_util::sync::CancellationToken;

#[derive(Serialize, Deserialize)]
struct EmailJob { to: String }

#[tokio::main]
async fn main() -> anyhow::Result<()> {
    let producer = Producer::<EmailJob>::connect(
        "redis://127.0.0.1:6379",
        ProducerConfig { queue_name: "emails".into(), ..Default::default() },
    ).await?;

    producer.add(EmailJob { to: "ada@example.com".into() }).await?;

    let consumer = Consumer::<EmailJob>::new(
        "redis://127.0.0.1:6379",
        ConsumerConfig { queue_name: "emails".into(), concurrency: 100, ..Default::default() },
    );

    consumer.run(|job| async move {
        println!("sending to {}", job.payload.to);
        Ok(bytes::Bytes::new())
    }, CancellationToken::new()).await?;

    Ok(())
}

Failed jobs retry with exponential backoff; exhausted ones land in the DLQ stream. See docs/engine.md for retry semantics, delayed jobs, idempotent scheduling, DLQ tooling, and observability hooks.

Quickstart — Node.js

chasquimq on npm. Single npm package, prebuilt binaries for darwin / linux / win32 (arm64 + x64).

npm install chasquimq
import { Queue, Worker } from "chasquimq"

const queue = new Queue("emails", { connection: { host: "127.0.0.1", port: 6379 } })

// Stable jobId: second call dedups on the same id.
await queue.addUnique("welcome", { to: "alice@example.com" }, { jobId: "welcome:alice" })

const worker = new Worker("emails", async (job) => {
    console.log(`processing ${job.name} (${job.id})`)
    return { delivered: true }   // captured when storeResults: true
}, { connection: { host: "127.0.0.1", port: 6379 }, storeResults: true })

worker.on("completed", (job) => console.log(`sent ${job.name}`))

// Block on the result from anywhere.
const job = await queue.add("welcome", { to: "ada@example.com" })
const result = await job.waitForResult({ timeoutMs: 30_000 })

Queue / Worker / Job / QueueEvents are the user-facing surface. Producer / Consumer / Promoter / Scheduler are re-exported from the same package for power users. See chasquimq-node/README.md.

Quickstart — Python

chasquimq on PyPI. abi3 wheels for Python 3.9+ on Linux (x86_64 + aarch64), macOS (x86_64 + aarch64), Windows (x86_64).

pip install chasquimq
import asyncio
from chasquimq import Queue, Worker, Job

async def send_email(job: Job) -> dict:
    print(f"sending {job.data}")
    return {"delivered": True}   # captured when store_results=True

async def main() -> None:
    queue = Queue("emails")

    job = await queue.add("welcome", {"to": "ada@example.com"})
    await queue.add_unique("welcome", {"to": "alice@example.com"}, job_id="welcome:alice")

    worker = Worker("emails", send_email, store_results=True)
    asyncio.create_task(worker.run())

    result = await job.wait_for_result(timeout=30.0)
    print(result)

    await worker.close()
    await queue.close()

asyncio.run(main())

Queue / Worker / Job / QueueEvents are the user-facing surface. Producer / Consumer / Scheduler are re-exported from the same package for power users. See chasquimq-py/README.md.

CLI

Install the chasqui operator binary. Fastest is cargo binstall chasquimq-cli (prebuilt tarball, ~3s); cargo install chasquimq-cli builds from source. No Rust toolchain? Use the platform-specific installer (all assets on the Releases page):

curl -LsSf https://github.com/jotarios/chasquimq/releases/latest/download/chasquimq-cli-installer.sh | sh

Once installed:

chasqui inspect emails              # one-shot: stream depth, pending, DLQ, delayed, repeatable
chasqui watch emails                # auto-refreshing dashboard
chasqui dlq peek emails             # render DLQ entries with their failure reason
chasqui dlq replay emails --limit 50
chasqui repeatable list emails
chasqui events emails               # tail the events stream
chasqui pause emails                # durably pause every consumer of the queue
chasqui resume emails               # lift the pause

Documentation

Full docs at chasquimq.io:

  • Getting started — install, first job, retries, the CLI.
  • Concepts — delivery semantics, Redis Streams primer, retry/backoff, the scheduler, architecture decisions.
  • Guides — configure retries, route/replay the DLQ, result storage, repeatable jobs, observe the engine, tune for throughput, produce from AWS Lambda, migrate from BullMQ / Sidekiq / Celery.
  • ReferenceRust, Node, and Python APIs, CLI, options, wire format, error codes.
  • Benchmarks — methodology, the 1.0 numbers, regressions and floors.

In-repo: docs/engine.md (engine internals), docs/history.md (slice-by-slice changelog).

Feature comparison

Feature ChasquiMQ BullMQ Bull Bee
Backend Redis Redis Redis Redis
Language Rust Node Node Node
Wire format MessagePack JSON JSON JSON
Native Node SDK
Native Python SDK
Pipelined / batched acks ✓ (default) opt-in
Idempotent produce (IDMP)
Stable job IDs (addUnique)
Result backends (getJobResult / waitForResult)
Event-driven completion wait (waitUntilFinished)
Worker / Queue / Job event listeners (EventEmitter-style) partial
Persistent job progress (updateProgress / progress event)
Per-job log stream (Job.log / Queue.getJobLogs)
Delayed jobs
Idempotent delayed scheduling
Cancel scheduled job
Retries (exponential backoff)
Repeatable / cron jobs
Dead-letter queue
First-class observability hooks ✓ (MetricsSink) 3rd-party 3rd-party
TLS (rediss://, ElastiCache encryption-in-transit)
TCP keepalive + automatic reconnect tuning ✓ (ConnectionTuning) partial
Redis Cluster (multi-shard / ElastiCache Cluster) ✓ (redis-cluster://)
Rotating-token credential hook (ElastiCache IAM) ✓ (Rust)
CLI dashboard ✓ (chasqui) 3rd-party 3rd-party
Priorities Future
Rate limiter Future
Pause / Resume
Job maintenance (remove / drain / clean / obliterate)
Parent / child dependencies Future
Web UI Future
Optimized for Throughput Jobs Jobs Messages

"Future" rows aren't on the current roadmap. If one is blocking for you, please open an issue.

Repo layout

chasquimq/                  engine crate
chasquimq-node/             Node.js bindings (NAPI-RS) + high-level shim
chasquimq-py/               Python bindings (PyO3) + high-level shim
chasquimq-cli/              `chasqui` binary
chasquimq-bench/            benchmark harness
chasquimq-metrics/          opt-in MetricsSink → metrics-rs / Prometheus adapter
benchmarks/                 results, methodology, reproduction
docs/                       design docs

Roadmap

Phases 1–4 shipped (engine, delayed jobs + retries, Node bindings, Python bindings + CLI). 1.0 polish complete: stable jobId + addUnique, opt-in result backends, Job.waitForResult polling helper, MissedFiresPolicy on cron specs, Python-handler-in-loop + FFI buffer-copy benches.

1.x cloud-Redis polish (May 2026) added TLS (rediss://), TCP keepalive + reconnect-policy tuning, Producer::shutdown clean disconnect, and a CredentialProvider hook for rotating-token auth (ElastiCache IAM) — see docs/history.md for the slice writeup.

Future v1.x candidates: priorities, rate limiter, parent/child dependencies, fair queues, web UI.

Contributing

PRs welcome. For anything beyond a small fix, please open an issue first — ChasquiMQ has load-bearing constraints (Streams, MessagePack, pipelined acks) that aren't obvious from the code alone. See CONTRIBUTING.md.

License

MIT — see LICENSE.

About

ChasquiMQ is a Redis-backed message broker / background job queue

Topics

Resources

License

Contributing

Stars

Watchers

Forks

Packages

 
 
 

Contributors