Introduction
Rhythm is a durable execution framework designed to orchestrate long-running workflows with minimal infrastructure overhead. Unlike traditional durable execution engines that rely on event replaying to reconstruct state, Rhythm utilizes a custom embedded scripting engine that checkpoints its exact execution state to a database. This allows workflows to pause and resume across process restarts or failures without the determinism constraints or cognitive overhead associated with replay-based systems.
Key Concepts
Rhythm divides logic into two primary primitives: Workflows and Tasks.
Workflows (.flow)
Workflows are written in a simplified, JavaScript-like syntax and stored in .flow files. They serve as the orchestration layer. Because the Rhythm engine is written in Rust and embedded into your application, these scripts are sandboxed and intentionally limited to keep logic focused on flow control.
- Durable Resumption: When a workflow hits an
awaitpoint, the entire runtime state is persisted to Postgres. - Immutable Versioning: Scripts are versioned by content hash. In-progress workflows are pinned to the version they started with, allowing for safe deployments even during active executions.
- Simplified Logic: No need to worry about "side effect" wrappers for basic logic like loops or date calculations, as there is no replay history to maintain.
Tasks
Tasks are written in your application's native language (e.g., Python). They represent the units of work that perform side effects, such as hitting external APIs or querying your primary database.
- Standalone or Orchestrated: Tasks can be invoked by a workflow or queued directly as simple background jobs.
- Retries and Timeouts: Tasks inherit the same reliability features as workflows, including configurable retry policies and execution tracking.
Technical Architecture
Rhythm's architecture is centered around a "stateless" core designed for high availability and easy scaling.
- Core Engine: A Rust-based VM that handles parsing, execution, and state persistence.
- Database: Postgres serves as the single source of truth for the work queue, scheduled items, and execution states.
- Host SDKs: Language-specific libraries (like the Python SDK) that provide the interface for defining tasks and interacting with the
Client.
Workflow Example
Workflows use a custom syntax that supports standard control structures (try/catch, for, if/else) and specialized global objects like Task, Signal, and Inputs.
// workflows/process_order.flow
// 1. Execute a task and wait for the result
let payment = await Task.run("process-payment", {
amount: Inputs.total,
userId: Inputs.userId
})
// 2. Pause and wait for an external signal (e.g., a webhook)
try {
let approval = await Signal.when("manager-approval", { timeout: "48h" })
} catch (err) {
// 3. Handle timeouts or errors reliably
return await Task.run("cancel-order", { orderId: Inputs.orderId })
}
return { status: "shipped", paymentId: payment.id }
System Requirements
Rhythm is designed to be "operationally boring." It has minimal hosting requirements:
- Database: PostgreSQL 11+
- Application: Any environment capable of running the Rust-backed SDK (e.g., Linux, macOS, Windows).
Current Status
[!WARNING] Rhythm is currently in Early Access. While the core execution model is stable, many features (such as comprehensive monitoring UI and advanced scheduling) are still in development. It is recommended for evaluation, internal tooling, or hobby projects. Backwards compatibility of the database schema and
.flowsyntax is not yet guaranteed.