Use one-off tasks for operational scripts that need normal Autumn context but should not become HTTP routes: backfills, cleanup jobs, customer-specific data fixes, replay scripts, and reports.

Tasks run in the app binary through autumn task <name>. The framework loads the active profile, initializes tracing, creates the configured database pool, installs mail/config extractors, runs startup hooks, executes the task, then runs shutdown hooks.

Declare A Task

Rust
use autumn_web::config::AutumnConfig;
use autumn_web::prelude::*;
use serde::Deserialize;

#[derive(Debug, Deserialize)]
pub struct CleanupArgs {
    #[serde(default)]
    pub confirm: bool,
}

/// Clean up unpublished draft posts.
#[autumn_web::task(name = "cleanup-posts")]
pub async fn cleanup_posts(
    mut db: Db,
    config: AutumnConfig,
    TaskArgs(args): TaskArgs<CleanupArgs>,
) -> AutumnResult<()> {
    if !args.confirm {
        autumn_web::reexports::tracing::info!(
            profile = ?config.profile,
            "dry run; pass --confirm to apply changes"
        );
        return Ok(());
    }

    // Use `db` exactly as you would in a route handler.
    Ok(())
}

Register it on the app builder:

Rust
mod tasks;

use autumn_web::prelude::*;

#[autumn_web::main]
async fn main() {
    autumn_web::app()
        .routes(routes![index])
        .one_off_tasks(one_off_tasks![tasks::cleanup_posts])
        .run()
        .await;
}

Run Tasks

List registered tasks:

Shell
autumn task --list

Run a task with the active profile:

Shell
autumn task cleanup-posts --confirm
autumn task --profile prod cleanup-posts --confirm

Workspace apps can select a package and binary:

Shell
autumn task --package blog --bin blog --list
autumn task --package blog cleanup-posts --confirm

Task arguments use long-flag syntax. Flags become snake_case fields on TaskArgs<T>:

Shell
autumn task backfill-user --user-id 42 --dry-run

deserializes as:

Rust
#[derive(serde::Deserialize)]
struct BackfillArgs {
    user_id: i64,
    dry_run: bool,
}

A task returning Err(AutumnError) exits non-zero and prints the error to stderr, so CI and cron can rely on normal process status.

Generate A Skeleton

Shell
autumn generate task cleanup_users

This creates tasks/cleanup_users.rs with a #[task] skeleton and adds serde if the project does not already depend on it. To register a generated root-level task file from src/main.rs:

Rust
#[path = "../tasks/cleanup_users.rs"]
mod cleanup_users_task;

autumn_web::app()
    .routes(routes![index])
    .one_off_tasks(one_off_tasks![cleanup_users_task::cleanup_users]);

For larger apps, keeping task modules under src/tasks/ and using normal Rust module declarations is often cleaner. The runtime only requires that the task function is registered with .one_off_tasks(...).