Library / SDK
apalis-dev/apalis avatar
apalis-dev/apalis

apalis Background Job Processing in Rust

Type-safe, extensible, and high-performance background processing library for Rust

1,466 stars99 forksRustMIT

At a glance

What is it?
apalis is a Rust library for running typed background jobs through asynchronous workers, middleware, storage adapters, and scheduling features. It suits applications that need more control than an in-process queue offers, but its backend choices and operational requirements need careful evaluation.
Who is it for?
Adopt apalis when a Rust service needs typed job handlers, explicit middleware, and selectable persistence or queue backends. Do not adopt it merely because the core crate is attractive if the application requires a broker or database not represented in the project.
Can I use it commercially?
Yes. MIT is a permissive licence: you can use, modify and sell software built on it, as long as you keep its copyright and licence notices.
Is it still maintained?
Yes. The repository last received commits 1 day ago.
What is it written in?
Mainly Rust, according to GitHub's language statistics.

Answers come from the project's GitHub data, last synced on October 23, 2026, and from our analysis. They are not legal advice.

From daily snapshots

Star history

  • apalis-dev/apalis1,466 ★ · +50
Star history
Repository2026-10-162026-10-23
apalis-dev/apalis1.4k1.5k

50 Stars in the last 7 days, measured from the daily GitHub snapshot. Compare with other projects

Editorial analysis

The queueing problem apalis addresses

apalis addresses work that should not block an HTTP request or another latency-sensitive Rust operation. Examples in the repository include sending email, monitoring workers, handling retries, enforcing graceful shutdown, and collecting observability data through tracing, Sentry, Prometheus, or OpenTelemetry. The intended audience is Rust developers who want background processing represented by ordinary asynchronous functions rather than opaque closures passed to a generic scheduler.

The central crate is only part of a wider system. Repository entries include `apalis-core`, `apalis-workflow`, and the main `apalis` crate. The documented crate ecosystem also separates queue integrations from persistence implementations. `apalis-amqp`, `apalis-nats`, and `apalis-rsmq` sit under message queues. `apalis-redis`, `apalis-sqlite`, `apalis-postgres`, `apalis-mysql`, and `apalis-pgmq` are listed as persistence backends. `apalis-cron` belongs to scheduling.

This matters because background processing has more than one dimension. A project may need delayed execution without distributed persistence, or it may need jobs distributed through an existing RabbitMQ-compatible, NATS, or RSMQ system. apalis does not force every application into one storage model at the core. It provides a common task model while leaving the queue or persistence mechanism in separate crates. That separation is useful for a service with established infrastructure, although it also makes backend selection part of adoption rather than a later implementation detail.

Typed handlers, futures, and worker execution

The documented execution model begins with task handlers as async functions. The API is described as macro-free, which gives developers direct control over handler signatures instead of requiring a registration macro. Repository examples cover basic workers, dependency injection, dynamic worker counts, task and worker context, panic catching, long-running jobs, and graceful shutdown. These directory names establish several operational concerns, but the README does not document their complete APIs.

Workers are described as lazy in a `Future`-like way. They do nothing until they are polled or woken, and the README specifically contrasts this with busy-waiting. That design is appropriate for asynchronous services because an idle worker does not need to poll continuously for work. It also means an application must use the runtime and wake-up path expected by its selected storage adapter. The documentation states compatibility with Tokio, async-std, and other async runtimes, so the library is not tied to one runtime interface.

The dependency-injection style is described as similar to frameworks such as Actix and Axum. That comparison concerns how services and middleware are composed, not an assertion of runtime compatibility. apalis uses the `tower` ecosystem for middleware and service utilities. This makes cross-cutting behavior composable around task processing rather than requiring every retry, timeout, or context feature to be embedded directly in a handler. The exact middleware order and error semantics must be checked against the relevant API documentation because the README does not provide them.

Retries, limits, priorities, and job state

The feature list gives apalis explicit controls for retries, rate limiting, timeouts, idempotency, and error handling. It also names prioritization, scheduling, metadata, and result tracking. These capabilities address failure modes that appear in any durable queue: repeated transient failures, work arriving faster than it can be completed, duplicate delivery, and the need to inspect a job after processing.

The repository includes dedicated examples for `retries`, `unique-jobs`, `long-running`, and `monitor`. Their presence confirms that these are supported use cases, but it does not establish a default retry count, retry delay, idempotency scope, or terminal-state policy. Those values cannot be inferred from the feature list. An adopting service must decide whether failed jobs are retried in memory or through its backend, how errors are classified, and what happens when a job succeeds after a worker loses its connection.

Rate limiting and concurrency controls also require an operational boundary. The README says distributed backends support configurable concurrency and multi-threaded execution. It does not say that concurrency is automatically coordinated across every process, nor does it describe a global rate limit. If multiple replicas consume the same queue, backend semantics and middleware configuration become essential. The optional web interface is described as a way to manage and monitor tasks, but the README does not confirm whether it is bundled with the core crate or how its access control is configured.

Backend selection and upgrade implications

apalis offers both specialized queues and relational or Redis-backed persistence. This is a genuine extension point, but it creates a larger evaluation surface than a single embedded queue. Redis, SQLite, PostgreSQL, MySQL, PGMQ, AMQP, NATS, and RSMQ do not offer identical administrative requirements or operational dependencies. The README lists them, but it does not provide a compatibility matrix beyond the categories shown in its tables.

For a Rust service already standardized on Tokio and PostgreSQL, the PostgreSQL adapter may avoid introducing a separate queue platform. For a deployment that already operates NATS or an AMQP system, the corresponding crate follows an approach in which jobs pass through an existing message system rather than living only in the service process. In-memory storage is also listed in the feature description, making it relevant for local execution and tests, although the README does not state its durability guarantees.

The repository is a Cargo workspace with Rust edition 2024 and `rust-version = "1.85"`. Its workspace configuration forbids unsafe code and includes lint settings for areas such as awaiting while holding locks, unused results, redundant clones, and documentation. Upgrade cost depends on the separate crates in use, not only the root `apalis` package. Recent releases include `v1.0.0`, `v1.0.0-rc.12`, and `v1.0.0-rc.11`, all dated in October 2026. The repository is not archived, and its last push was on 2026-10-12. That indicates recent repository activity, but it does not prove that every backend crate follows the same release cadence.

The project is licensed under MIT. That generally makes the code available under permissive terms, but application owners still need to review dependency licenses and comply with the MIT notice. The repository's `deny.toml` and `supply-chain` directory are visible in the layout, while the README does not document a complete license audit procedure.

Installing apalis and starting a real worker

The README directs users to the `apalis` package on crates.io and links to the API documentation on docs.rs. It also points to separate backend crates and their example repositories. However, the README does not include an installation command, Cargo dependency snippet, or complete first-use program. Inventing a version or adapter feature flag would make the tutorial less trustworthy, so no installation code is included here.

A practical first evaluation should begin with the linked `examples/basic` directory, then select one storage crate rather than adding every adapter. The repository also contains `examples/deps-injection`, `examples/retries`, `examples/graceful-shutdown`, and `examples/prometheus`. Those examples cover the sequence most teams need to evaluate: define a handler, provide its dependencies, start a worker, configure failure handling, and add shutdown or observability behavior.

Before writing application code, check the documentation for the chosen backend and runtime. Confirm the exact crate name, feature flags, storage initialization, worker startup method, and shutdown call in that backend's repository. Then run the smallest example against the same infrastructure planned for production. The expected first result is not merely a compiling worker. It is a submitted job reaching a terminal or observable state, including the behavior of a deliberately failing job and a job interrupted during shutdown.

Where apalis is the wrong fit

apalis is a poor fit for an application that needs only a small in-process background queue and values minimal dependencies above middleware, backend adapters, scheduling, monitoring, and distributed execution options. The project's feature set is extensive, and adopting the full ecosystem may introduce more operational decisions than the application actually needs.

It is also the wrong choice when the required infrastructure is absent from the documented crates and no external adapter is planned. Naming a message queue in an architecture diagram does not make it compatible. Teams using a broker not represented in the crate ecosystem would first need a clear technical reason to build or maintain an adapter.

Another limitation is documentation depth. The README names monitoring, metrics, graceful shutdown, error reporting, and a web interface, while the repository includes examples for tracing, Sentry, Prometheus, OpenTelemetry, and graceful shutdown. It does not document their configuration. Likewise, it does not state default delivery guarantees, recovery behavior after process termination, retry classifications, or deployment requirements. apalis should therefore be judged as a library plus selected integrations, not as a complete background-processing service whose operational behavior can be inferred from its feature list.

apalis compared with an existing broker integration

A real alternative is to expose an existing queue or persistence system through a thin application-specific worker rather than adopting the complete apalis stack. Both approaches can move email, scheduled, or long-running work out of a request path. The difference is ownership of the processing layer. A thin integration leaves queue polling, retries, concurrency, middleware, and job-state behavior inside application code. Apalis centralizes those concerns in a Rust task model with handlers, middleware, workers, and optional adapter crates.

The apalis approach is more attractive when several services need similar processing behavior or when the team wants to compose `tower` middleware around tasks. It is especially relevant when one of the listed backends matches deployed infrastructure. The application-specific worker can be simpler when there is one queue, one consumer, and a small set of handlers. It also avoids adopting abstractions that the service will not use.

The decision should be based on the required semantics, not on the phrase "high-performance" in the project description. Confirm delivery behavior, retry ownership, idempotency, scheduling, and observability before choosing. Apalis supplies building blocks for those concerns, while a direct broker integration can expose them more explicitly. Neither choice resolves reliability without correct storage, worker, and deployment configuration.

Editorial conclusion

Adopt apalis when a Rust service needs typed job handlers, explicit middleware, and selectable persistence or queue backends. Do not adopt it merely because the core crate is attractive if the application requires a broker or database not represented in the project. Verify first that your required backend, runtime, Rust version, retry behavior, monitoring needs, and operational recovery model match the v1.0.0 APIs and examples.

Frequently asked questions

What is apalis used for in Rust?

apalis is used to define async task handlers and process background jobs with workers. Its documented features include retries, scheduling, concurrency, middleware, result tracking, and multiple queue or persistence backends.

Which storage backends does apalis support?

The README lists in-memory storage, Redis, PostgreSQL, SQLite, MySQL, and PGMQ under storage support. It also lists AMQP, NATS, and RSMQ integrations as message queues.

Does apalis require Tokio?

No. The README says apalis works with Tokio, async-std, and other async runtimes. The chosen runtime and backend still need to be checked for the configuration required by their adapters.

Official sources

  1. apalis-dev/apalis on GitHub
  2. License: MIT
  3. Project website
  4. README
  5. Releases
Add this badge to your README

If you maintain this project, the badge below links readers to this analysis and shows its maintenance status from the daily GitHub snapshot. Paste the markdown into your README; add ?metric=license or ?metric=stars to the image URL for a different field.

Add this badge to your README

markdown
[![Hysen Labs](https://hysenlabs.com/badge/apalis-dev-apalis.svg)](https://hysenlabs.com/projects/apalis-dev-apalis)

Star history chart for your README

markdown
[![Star history](https://hysenlabs.com/chart/apalis-dev-apalis.svg)](https://hysenlabs.com/projects/apalis-dev-apalis)

Was this useful?