Boson

Short-lived background work

Boson is a durable Rust background job runtime with typed tasks, retries, rate limits, leases, and pluggable backends for in-memory, SQLite, PostgreSQL, Redis, and NATS—built so enqueue and worker dispatch stay out of ad hoc scripts.

Why this family exists

Boson owns enqueue orchestration, worker dispatch, leases, retries, and task configuration. Your application owns business logic, identity mapping, and backend choice. That split keeps checkout fanout, invoice batches, and similar short-lived work observable and retryable without reinventing a queue per product.

Where it lands

Marketing workload recipes and counter-app demos enqueue Boson tasks for background fanout while the UI stays responsive—same Valence models, durable retries instead of fire-and-forget.
Register tasks with #[task], boot via Boson::builder() with a queue backend and ExecutionContext factory, then enqueue with send_with. Scale from embedded mem to durable stores and remote workers without changing the task surface. Axum-friendly wiring and broker e2e coverage (postgres/redis/nats) land in CI; see docs.rs/uf-boson for the guided embedded vs remote-worker get-started.

In the workspace

Marketing workload recipes and counter-app demos enqueue Boson tasks for background fanout while the UI stays responsive—same Valence models, durable retries instead of fire-and-forget.

Code sample

From the upstream getting-started docs — see also all code recipes on Resources.
Boson taskBoson
Typed #[task] + enqueue
use std::sync::Arc;
use boson::{
    configure, task, Boson, ExecutionContext, JsonExecutionContextFactory,
    MemQueueBackend,
};

#[task(name = "process_order")]
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(())
}