BosonImplemented
Short-lived background work
Boson is a durable background task runtime for Rust: typed tasks, retries, rate limits, leases, and queues on memory, SQLite, Postgres, Redis or NATS. Enqueue from a request and let the workers do the rest.On this site
The counter demo on this site enqueues Boson tasks for background fanout while the UI stays responsive. It uses the same Valence models, and failed tasks retry from durable storage.Typed tasks
Implemented
Register typed payloads and handlers with #[task], then enqueue them through send_with.
Retries, leases, and limits
Implemented
Set priority, attempts, backoff, in-flight limits, enqueue rate and idempotency on each #[task]. The admin UI can change them later.
Worker pools
Implemented
Send each task to a named pool and pick which pools each worker drains. The admin UI shows each task's effective pool and lets you change its priority.
Gluon hardware placement
Partially Implemented
Run a pool's workers on a Gluon pool with its own minimum vCPU, memory and disk. The pool names are matched by hand for now.
Queue adapters
Implemented
Use memory, SQLite or Postgres queues from uf-boson, or Redis and NATS through their adapter crates.
Embedded and remote workers
Implemented
Run enqueue and workers in one process or split workers into their own services.
HTTP administration
Implemented
Mount the Boson Axum router for authenticated task, queue, and runtime operations.
Boson operator UI
Implemented
Inspect tasks, queue state, runs, and configuration on this host at /boson.
Worker poolsPartially Implemented
Run each task on the hardware it needs
Tag a task with a pool, and only workers that drain that pool will run it. On hosts managed by Gluon, each pool's workers can sit on different hardware: small machines for welcome emails, 8 vCPUs and 32 GB for PDF rendering. Tasks without a pool run on the default pool, named global.#[task(name = "render_pdf", pool = "render")]
async fn render_pdf(ctx: Box<dyn ExecutionContext>, doc_id: String) -> boson_core::Result<()> {
// ...
}
// On the render machines, drain only the render pool:
let boson = Boson::builder().worker_pools(["render"]) /* ... */ .build()?;Needs Gluon →For now you keep the Boson and Gluon pool names in sync yourself. The task config page doesn't list Gluon pools yet.
Your tasksWorker poolGluon pool (minimum hardware)
send_welcome_email#[task(pool = "global")]
→global
→generalmin 2 vCPU · 4 GB
render_pdf#[task(pool = "render")]
→render
→rendermin 8 vCPU · 32 GB · 50 GB disk
See it in action
Code sample
Taken from the getting-started docs. See all code samples on Resources.
Boson taskBoson
Typed #[task] with retry settings, then enqueue
use std::sync::Arc;
use boson::{
configure, task, Boson, ExecutionContext, JsonExecutionContextFactory,
MemQueueBackend,
};
#[task(name = "process_order", max_attempts = 5, max_in_flight = 20)]
async fn process_order(
ctx: Box<dyn ExecutionContext>,
order_id: String,
amount_cents: u64,
) -> boson_core::Result<()> {
tracing::info!(actor = ctx.label(), %order_id, amount_cents);
Ok(())
}
#[tokio::main]
async fn main() -> anyhow::Result<()> {
let boson = Boson::builder()
.queue_backend(Arc::new(MemQueueBackend::new()))
.execution_context_factory(JsonExecutionContextFactory)
.auto_registry()
.build()?;
configure(boson);
ProcessOrder::send_with(
serde_json::json!({"System": {"operation": "checkout"}}),
ProcessOrderParams {
order_id: "ord-42".into(),
amount_cents: 9900,
},
)
.await?;
Ok(())
}