Skip to content

Sayiir — Fast, Simple Durable Workflow Engine

The fast, simple durable workflow engine. Graph-based, continuation-driven execution — just write normal Python, TypeScript, or Rust. Native performance, automatic checkpointing, no infrastructure to deploy.

Zero Learning Curve

Clean, typed, idiomatic APIs in Python, TypeScript, and Rust. No DSL, no YAML — just familiar patterns.

Library Not Platform

pip install sayiir, pnpm add sayiir, or add a Cargo dep. No orchestrator to deploy.

Native Rust Performance

Rust core, no replay overhead. JSON by default, swap to zero-copy rkyv or any binary codec.

Pluggable & Lightweight

Swap backends, codecs, runners. InMemory for tests, Postgres for production.

See it in action
from sayiir import task, Flow, run_workflow
@task
def fetch_user(user_id: int) -> dict:
return {"id": user_id, "name": "Alice"}
@task
def send_email(user: dict) -> str:
return f"Sent welcome to {user['name']}"
workflow = Flow("welcome").then(fetch_user).then(send_email).build()
result = run_workflow(workflow, 42)
import { task, flow, runWorkflow } from "sayiir";
const fetchUser = task("fetch-user", (userId: number) => {
return { id: userId, name: "Alice" };
});
const sendEmail = task("send-email", (user: { id: number; name: string }) => {
return `Sent welcome to ${user.name}`;
});
const workflow = flow<number>("welcome")
.then(fetchUser)
.then(sendEmail)
.build();
const result = await runWorkflow(workflow, 42);
use sayiir_runtime::prelude::*;
#[task(timeout = "30s", retries = 3)]
async fn fetch_user(id: u64) -> Result<User, BoxError> {
db.get_user(id).await
}
#[task]
async fn send_email(user: User) -> Result<(), BoxError> {
email_service.send_welcome(&user).await
}
let workflow = workflow! {
name: "welcome",
steps: [fetch_user, send_email]
}.unwrap();

Sayiir Server — Coming Soon

Same workflows, same code — plus a managed platform with a web dashboard, multi-tenancy, scheduled triggers, observability, and Kubernetes-native deployment. Learn more →