Skip to content

Horsies

PostgreSQL-backed background task queue and workflow engine for Rust.

AI agents: see llms.txt for a complete sitemap and keyword index of these docs. If you are working from source, agent guidance skills are in horsies/.agents/skills/ (SKILL.md, tasks.md, workflows.md, configs.md, practical-summary.md).

NOTE: There is a python version of this library, even though rust and python versions have almost the same api and mental model, they are not interoperable!

Postgres Based

Postgres based.

Type-safe Tasks

Tasks return typed TaskResult — errors as values, not panics.

Real-time Dispatch

PostgreSQL LISTEN/NOTIFY for instant task delivery — no polling.

Workflow Engine

DAG based workflow definitions for orchestrating complex task pipelines.

Scheduled Tasks

Type-safe, human-readable schedule patterns — no cron strings.

Multi-queue Support

Priority-based queues with per-queue concurrency limits.

TUI Monitoring

Syce TUI dashboard for monitoring workers, tasks, and workflows.

use horsies::{
Horsies, AppConfig, TaskResult, TaskError, task,
};
use serde::{Deserialize, Serialize};
#[derive(Debug, Clone, Serialize, Deserialize)]
struct AddInput { a: i32, b: i32 }
#[task("add_numbers")]
async fn add_numbers(input: AddInput) -> Result<i32, TaskError> {
Ok(input.a + input.b)
}
#[tokio::main]
async fn main() -> Result<(), Box<dyn std::error::Error>> {
let mut app = Horsies::new(AppConfig::for_database_url(
"postgresql://user:pass@localhost:5432/mydb"
))?;
add_numbers::register(&mut app)?;
// Start a worker in another process/thread to execute tasks.
// Here we just send a task and wait for the result.
match add_numbers::send(AddInput { a: 5, b: 3 }).await {
Ok(handle) => match handle.get(None).await {
TaskResult::Ok(value) => println!("{}", value), // 8
TaskResult::Err(err) => println!("Task failed: {:?}", err.error_code),
},
Err(err) => println!("Send failed: {}", err.message),
}
Ok(())
}