Comparison
FlexiQ against Temporal, Cloud Tasks and EventBridge, BullMQ, Celery, Dramatiq and RQ — where each one is the better choice.
FlexiQ against Temporal, Cloud Tasks and EventBridge, BullMQ, Celery, Dramatiq and RQ — where each one is the better choice.
TL;DR: FlexiQ is one Rust engine under four SDKs — Python, Node, Java and
Rust — plus a network door, flexiq-server, that any language reaches over
gRPC or JSON. It embeds the queue in your process, with durable steps and
workflows on top, and starts on a SQLite file with nothing else installed. When
you outgrow one machine, the same code moves to Postgres or Redis.
Steps and workflows sit on top of the queue, not the other way round: FlexiQ is a task queue first. The tools people actually weigh it against are a durable-execution platform (Temporal), managed cloud queues (Cloud Tasks, EventBridge), and the incumbent queue in each language (BullMQ, Celery, Dramatiq, RQ). This page says where each of them is the better choice. For speed, see Benchmarks — measured, reproducible, and not flattering on every axis.
FlexiQ fits when:
flexiq-server when a
caller has no SDKReach for something else when:
| FlexiQ | Temporal | Cloud Tasks / EventBridge | BullMQ | Celery | Dramatiq | RQ | |
|---|---|---|---|---|---|---|---|
| What it is | Embedded task queue with durable steps and workflows | Durable-execution platform | Managed task queue (Cloud Tasks) and managed event bus (EventBridge) | Queue library for Node.js | Distributed task queue for Python | Task queue for Python | Task queue for Python on Redis |
| What you run | Nothing beyond your app on SQLite; Postgres or Redis to scale out; optionally flexiq-server | A Temporal Service — frontend, history, matching and worker services plus a database — and your Workers; or Temporal Cloud and your Workers | Your targets; the queue is the cloud provider's | Redis, or PostgreSQL since BullMQ 6, and your workers | A broker (RabbitMQ or Redis), usually a result backend, and your workers | A broker (RabbitMQ or Redis) and your workers | Redis and your workers |
| Languages | Python, Node, Java, Rust SDKs; Go and Ruby clients; any gRPC or HTTP caller | Go, Java, Python, TypeScript, .NET, PHP, Ruby, Rust SDKs | Any — a target is an HTTP endpoint or a cloud service | Node.js and Bun; ports for Python, .NET, Rust, Elixir and PHP (producer only) | Python | Python | Python |
| Durable steps | Yes — memoized step.run, step.sleep | Yes — Activities, with workflow code replayed from history | No | No built-in; a documented pattern saves the step in job data | No | No | No |
| Workflow model | DAG declared up front: fan-out, conditions, approval gates, sub-workflows, sagas | Workflows are code, replayed deterministically; signals, queries, updates, durable timers | None — one task or event, one target | Flows (parent and child jobs) | Canvas: chain, group, chord | Pipelines and groups | Job dependencies |
| Code changes under in-flight work | No versioning API; a changed step sequence dead-letters the job, so deploying one is a drain | Worker Versioning and patching | n/a — no in-flight state | — | — | — | — |
| Dead-letter queue | Yes — inspect the payload and error, replay as a fresh job | No queue — a failed execution keeps its history and can be reset to an earlier point | Cloud Tasks deletes a task after its last attempt; EventBridge sends to an SQS queue, if you attach one, whose redrive is code you write | Failed set; job.retry() | No built-in | Yes — dead-lettered messages kept up to 7 days | Failed job registry |
| Local development | A SQLite file, nothing to install | temporal server start-dev, in memory unless given a file | No official emulator for Cloud Tasks; EventBridge only through third-party emulators such as LocalStack | A local Redis | A local broker | A local broker | A local Redis |
| Hosted offering | None | Temporal Cloud | Fully managed | None for the queue; Taskforce.sh is a hosted dashboard | None | None | None |
| Web UI | Built-in dashboard | Temporal Web UI | The cloud provider's console | Taskforce.sh, or community boards | Flower | Community dashboards | rq-dashboard |
| Performance | Benchmarked | Not measured | Not measured | Benchmarked | Benchmarked | Benchmarked | Benchmarked |
The benchmark is one scenario and it cuts both ways: against a Redis a network hop away, FlexiQ's Redis backend is the slowest entrant in the run — behind BullMQ, Celery, Dramatiq and RQ alike — and Where FlexiQ loses explains why. Temporal and the managed services were not part of the run, so this page makes no performance claim about them either way.
Temporal and FlexiQ overlap on one idea — durable execution with memoized
steps — and differ on nearly everything around it. In Temporal a workflow is
ordinary code that the platform replays deterministically from its event
history; side effects live in Activities, whose results are recorded so a
replay never repeats them. FlexiQ's
durable steps are the same idea inside a
single task: step.run commits a result next to the job and every later
attempt reads it back instead of running the work again.
Temporal's model goes much further, and for a large class of users it is the right answer:
What Temporal asks for in return is a service to operate. Self-hosted, that is
the Temporal Service — frontend, history, matching and worker services —
backed by Cassandra, PostgreSQL or MySQL; its SQLite store is for development
and testing only. Workflow code must stay deterministic, and changes to it go
through versioning. temporal server start-dev makes local development easy,
but production is a cluster or a Temporal Cloud account.
FlexiQ is one library in your process, or one flexiq-server binary, and runs
in production on a SQLite file when one machine is enough. It is a task queue
first — priorities, rate limits, cron, a dead-letter queue you replay from —
with steps and a DAG workflow engine added on top. Steps are capped in size (a
checkpoint, not a data store) and cannot change shape mid-flight.
Choose FlexiQ if you want a task queue with checkpointed retries and simple workflows, without running a cluster or adopting a programming model. Choose Temporal if your workflows are long-lived business processes, need signals or human-scale timers, or will change while executions are in flight — or if you want durable execution as a managed service.
Google Cloud Tasks and Amazon EventBridge are fully managed: there is no queue to run, patch or back up, and that is a real advantage FlexiQ cannot match. Cloud Tasks dispatches each task to an HTTP or App Engine target with a per-queue retry policy; EventBridge routes events to targets by rule.
Where they stop is where FlexiQ starts:
| FlexiQ | Cloud Tasks / EventBridge | |
|---|---|---|
| Operations | You run the database and, for push, flexiq-server | None |
| Exhausted retries | Kept in a dead-letter queue you can list, read and replay | Cloud Tasks deletes the task; EventBridge writes it to an SQS queue if you attach one, and redriving it is code you write |
| Durable steps | Yes, on a long-lived worker | No |
| Local development | Everything runs against a SQLite file | No official emulator for Cloud Tasks; third-party ones such as LocalStack for EventBridge |
| Who runs the work | SDK workers, attached executors or push targets, on the same queues | The targets the queue or rule dispatches to |
Migrating from Cloud Tasks and EventBridge maps each concept across and lists the limits worth knowing first.
Choose FlexiQ if you want a dead-letter queue you can replay from, durable steps, or a queue that runs on a laptop. Choose Cloud Tasks or EventBridge if nobody should operate anything for the queue and the targets already live in that cloud.
BullMQ is the Node incumbent: a mature library with priorities, rate limits, repeatable jobs and parent-child flows. It runs on Redis, and since BullMQ 6 also on PostgreSQL. It runs on Node.js and Bun, with ports for Python, .NET, Rust, Elixir and PHP (producer only) that share the same queues.
| FlexiQ | BullMQ | |
|---|---|---|
| Backend | SQLite with nothing installed; Postgres or Redis | Redis; PostgreSQL since BullMQ 6 |
| Core | Rust scheduler | JavaScript, with Lua scripts on Redis |
| Exhausted retries | Dead-letter queue with replay | Failed set, job.retry() |
| Durable steps | Built-in | A documented pattern: save the step in job data |
| Workflows | DAG, fan-out, approval gates, sub-workflows, sagas | Flows (parent and child jobs) |
| Other languages | Python, Java and Rust SDKs share the queue, all on one Rust engine | Ports of the library for other languages |
On a remote Redis, FlexiQ's Redis backend is the slowest entrant in the benchmark, and BullMQ is one of the two that win it outright.
Choose FlexiQ if you want to start without Redis, need durable steps, or want every language's workers on one engine rather than a port per language. Choose BullMQ if Redis is already central to your stack and you want its throughput and its ecosystem. The BullMQ migration guide maps every concept across.
Celery is the most widely used Python task queue — battle-tested, feature-rich, and distributed from the start. Like Dramatiq and RQ it is a Python tool; FlexiQ's Python SDK is its counterpart, and producers in other languages can enqueue to the same FlexiQ queues.
| FlexiQ | Celery | |
|---|---|---|
| Setup | pip install flexiq | A broker (RabbitMQ or Redis), usually a result backend, Celery itself |
| Configuration | Constructor parameters | Settings module or app config |
| Worker model | Rust OS threads, or a prefork pool | Prefork, eventlet or gevent pools |
| Distributed | Multi-server on Postgres or Redis | Yes, broker-based |
| Canvas | chain, group, chord, starmap, chunks | chain, group, chord, starmap, chunks, and more |
| Monitoring | Built-in dashboard | Flower |
Choose FlexiQ if you want a queue without a broker, durable steps, or a dead-letter queue out of the box. Choose Celery if you need its broker routing, its ecosystem of extensions, or its long production record. If you would run FlexiQ on a remote Redis, note that Celery outpaces FlexiQ's Redis backend in the benchmark.
Dramatiq is a reliable, performance-focused Python alternative to Celery.
| FlexiQ | Dramatiq | |
|---|---|---|
| Broker | None (SQLite), or Postgres or Redis | Redis or RabbitMQ |
| Priority | Yes, per job | Per actor, applied once messages are consumed |
| Rate limiting | Built-in | dramatiq.rate_limits helpers |
| Dead-letter queue | Built-in, replayable as a fresh job | Built-in, messages kept up to 7 days |
| Middleware | Hooks + per-task TaskMiddleware | Full middleware stack |
Choose FlexiQ if you want to run without a broker, or need durable steps and workflows. Choose Dramatiq if you already run its broker and want its throughput — on a remote Redis it is one of the two entrants that win the benchmark outright, where FlexiQ's Redis backend is the slowest.
RQ focuses on simplicity — a minimal Python task queue built on Redis.
| FlexiQ | RQ | |
|---|---|---|
| Broker | None (SQLite), or Postgres or Redis | Redis required |
| Priority | Yes (integer levels) | Separate queues for priority |
| Rate limiting | Built-in | No |
| Chaining | Yes | Job dependencies |
| Monitoring | Built-in dashboard | rq-dashboard |
Choose FlexiQ if you want similar simplicity without requiring Redis. Choose RQ if you already run Redis and want the smallest possible queue — on a remote Redis, RQ also outpaces FlexiQ's Redis backend in the benchmark.
| Feature | FlexiQ | Celery | RQ | Dramatiq | Huey | TaskIQ |
|---|---|---|---|---|---|---|
| Broker required | No | Redis / RabbitMQ | Redis | Redis / RabbitMQ | Redis | Redis / RabbitMQ / Nats |
| Core language | Rust + Python | Python | Python | Python | Python | Python |
| Priority queues | Yes | Yes | No | Yes (per actor) | Yes | Yes |
| Rate limiting | Yes | Yes | No | Yes | Yes (fixed window) | No |
| Dead letter queue | Yes | No | Yes | Yes | No | No |
| Task chaining | Yes (chain/group/chord) | Yes (canvas) | Dependencies only | Yes (pipelines) | Yes (pipelines, groups, chords) | Yes (pipelines) |
| Job cancellation | Yes | Yes (revoke) | Yes (job.cancel()) | No | Yes | No |
| Progress tracking | Yes | Yes (custom) | No | No | No | No |
| Unique tasks | Yes | No (manual) | No | No | Yes | No |
| Batch enqueue | Yes | No | No | No | No | No |
| Retry with backoff | Yes (exponential + jitter) | Yes | Yes | Yes | Yes | Yes |
| Periodic/cron tasks | Yes (6-field with seconds) | Yes (celery-beat) | Yes (built-in CronScheduler, beta) | Yes (APScheduler) | Yes | Yes (taskiq-cron) |
| Async support | Yes | No (no native asyncio; eventlet/gevent pools) | No | Yes (AsyncIO middleware) | — | Yes (native) |
| Cancel running tasks | Yes (cooperative) | Yes (revoke) | Yes (send_stop_job_command) | No | No | No |
| Soft timeouts | Yes | Yes (soft_time_limit; prefork pool, not eventlet or gevent) | No | No | No | No |
| Custom serializers | Yes | Yes | Yes (serializer=) | Yes (set_encoder) | — | Yes |
| Per-task middleware | Yes | No | No | Yes | No | Yes |
| Multi-process (prefork) | Yes | Yes | No | No | No | No |
| Namespace isolation | Yes | No | No | No | No | No |
| Result streaming | Yes (publish/stream) | No | No | No | No | No |
| Worker discovery | Yes (hostname/pid/status) | Yes (flower) | No | No | No | No |
| Lifecycle events | Yes (13 types) | Yes (signals) | No | Yes (actors) | No | No |
| Async canvas | Yes | No | No | No | No | No |
| OpenTelemetry | Yes (optional) | Yes (contrib) | No | No | No | Yes (built-in) |
| CLI | Yes | Yes | Yes | Yes | Yes | Yes |
| Result backend (where task return values are stored) | Built-in (SQLite) | Redis / DB / custom | Redis | Redis / custom | Redis / SQLite | Redis / custom |
| Setup complexity | pip install | Broker + backend | Redis server | Broker | Redis server | Broker + backend |
Huey is a lightweight task queue with Redis or SQLite backends.
| FlexiQ | Huey | |
|---|---|---|
| Backend | SQLite (Rust-native) | Redis or SQLite (Python) |
| Performance | Rust scheduler + OS threads | Python threads |
| Chaining | chain, group, chord | Pipelines, groups, chords |
| Rate limiting | Built-in token bucket | Fixed-window rate_limit |
| DLQ | Built-in | No |
| Progress | Built-in | No |
Choose FlexiQ if you want more features with SQLite. Choose Huey if you need a mature, well-documented SQLite-backed queue.
TaskIQ is a modern, async-native task queue. It's a good fit if you're fully async and already have a broker.
| FlexiQ | TaskIQ | |
|---|---|---|
| Broker | None (DB-backed) | Redis / RabbitMQ / Nats |
| Async | Native + sync | Async-first |
| Scheduler | Rust (Tokio) | Python |
| GIL (Global Interpreter Lock — only one thread runs Python bytecode at a time) | Rust scheduler bypasses GIL | Python scheduler competes for GIL |
| Setup | pip install flexiq | Install broker + taskiq + broker plugin |
Choose FlexiQ if you want zero infrastructure. Choose TaskIQ if you're fully async and already have Redis/Nats.
Most Node task queues need a server beside your app: Bee-Queue and Bull require Redis, BullMQ requires Redis (or, since version 6, PostgreSQL), and Agenda requires MongoDB. FlexiQ embeds the queue in a Rust core with a pluggable backend (SQLite, Postgres, or Redis), so you can start with zero infrastructure and add a server only when you scale out. BullMQ has its own section above.
| FlexiQ | Agenda | |
|---|---|---|
| Server | None (SQLite) — optional Postgres/Redis | MongoDB required |
| Core | Rust scheduler | JS + Mongo |
| Priorities / rate limits / DLQ | Built-in | Limited |
| Workflows | Builder DAG, fan-out, sub-workflows, sagas | No |
| Result streaming | Yes (publish/stream) | No |
Choose FlexiQ for a broker-optional queue with a workflow engine built in. Choose Agenda if MongoDB is already your system of record and cron-style scheduling is what you need.
JVM background-job tools each specialize: Quartz for cron scheduling, JobRunr for background jobs (RDBMS or Redis), Spring Batch for batch/ETL pipelines. FlexiQ is a general-purpose task queue with a Rust core: priorities, rate limits, dead-letter queues, workflows, and result streaming, backed by SQLite, Postgres, or Redis, usable standalone or via the Spring Boot starter.
| FlexiQ | Quartz | JobRunr | Spring Batch | |
|---|---|---|---|---|
| Focus | Task queue + workflows | Cron scheduling | Background jobs | Batch/ETL pipelines |
| Backend | SQLite / Postgres / Redis | Your RDBMS | Your RDBMS / Redis | Your RDBMS |
| Priorities / rate limits / DLQ | Built-in | No | Limited | No |
| Workflows | Builder DAG, fan-out, sub-workflows, sagas | No | No | Step/chunk model |
| Result streaming | Yes (publish/stream) | No | No | No |
Choose FlexiQ for a broker-optional queue with priorities, DLQ, and a workflow engine. Choose Quartz/Spring Batch for pure cron scheduling or chunk-oriented batch processing tightly coupled to Spring.
Looking to switch? See the
Migrating from CeleryBullMQJVM job schedulingflexiq-core
guide for a step-by-step walkthrough with side-by-side code examples. Coming
from a managed queue instead, Migrating from Cloud Tasks and
EventBridge covers the move to flexiq-server.