id_effect is a typed effect runtime for Rust: Effect<A, E, R>, capability-based dependency injection, structured concurrency, resilience, pull-based streams and a first-class testing kit — plus OTP-grade supervision and distribution for long-running supervised services, daemons and CLIs. The design is inspired by Effect (Effect-TS) and Erlang/OTP: programs describe work as lazy values, wire dependencies through the type system, run under an explicit runtime, and recover under supervision.
It is growing into a batteries-included platform (ADR 0012): the compiler checks your dependencies, errors and resources, the runtime supervises them, and one command gets you a production-shaped service. Today it ships the runtime, supervision, and integrations for Axum and SQL; further effect-native batteries (migrations, auth, jobs, mail, storage, an in-app console) and the id_effect_kit facade and id-effect CLI are planned for the releases leading to 1.0.
Typed Effects in Rust is the main way to learn id_effect: from Effect<A, E, R> and the effect! macro, through capabilities and providers, to concurrency, resources, scheduling, streams, schema, testing and supervision. The API docs answer “what does this type do?”; the book answers “how do I think in effects?”.
- Read online: Typed Effects in Rust (GitHub Pages)
- Terminology: Glossary
- Upgrading: Migration guide to 0.7 (from 0.6), to 0.6 (from 0.4 / 0.5), and the CHANGELOG
- Stability: semver, deprecation and MSRV policy
- Source:
crates/id_effect/book/(build locally withmdbook build crates/id_effect/book)
id_effect models programs as descriptions of work (Effect values) rather than immediate side effects. You compose them, attach requirements to the type signature, and run them when you choose:
Effect<A, E, R>— success typeA, error typeE, requirementsR.- Capabilities and providers — typed dependency injection: declare what an effect needs (
caps!,need), provide it once at the edge as aLayer(#[derive(ProviderSpecDerive)],provide_layer). pipe!andeffect!— composition and do-notation-style blocks without hiding what the types mean.- Structured concurrency and resilience — fibers, scopes, cancellation,
Schedule-driven retry, circuit breakers. - Pull-based streams — bounded-memory, incremental operators that work on infinite sources.
- Supervision and distribution —
id_effect_process(processes, links, monitors, supervision trees, gen_statem-style FSMs) andid_effect_node(Process Mesh across nodes). - Testing kit — the deterministic
TestExecutor(virtual clock:run_until_stalled,advance,next_timer_deadline), a seeded/fedTestRandom, and capability mocks provided as layers.
The core crate runs effects as fibers on a pluggable executor (a multi-thread TokioExecutor in production, the deterministic TestExecutor with a virtual clock in tests): Runtime::run(eff).await in async code, Effect::block_on / Runtime::block_on at a synchronous edge. The default compute feature adds the parallel Compute Fabric; id_effect_tokio is the Tokio runtime adapter.
Core
| Crate | Version | Description |
|---|---|---|
id_effect |
Effect<A, E, R>: lazy Send effects over a typed capability list, run on a fiber runtime (Tokio executor), with layers, streams, schedules and coordination | |
id_effect_config |
Configuration for id_effect: Config descriptors, ConfigProvider and Figment/serde loading | |
id_effect_logger |
EffectLogger capability for id_effect: log levels, annotations and pluggable backends over tracing | |
id_effect_macro |
Declarative macros re-exported by id_effect: pipe!, err! | |
id_effect_proc_macro |
Procedural effect! macro for the effect crate (proc-macro only; declarative macros live in id_effect_macro) |
|
id_effect_resilience |
Resilience patterns for id_effect: circuit breaker, Schedule-driven retry, rate limiter, bulkhead, hedged requests, fallback, policy pipelines | |
id_effect_tokio |
Tokio runtime adapter for id_effect: TokioRuntime over the 0.7-kernel TokioExecutor (fibers as tokio tasks) |
Runtime and supervision
| Crate | Version | Description |
|---|---|---|
id_effect_fsm |
Typed finite-state machines with Effect-valued transitions, derive(Fsm), sagas, and a gen_statem-style process behaviour for id_effect | |
id_effect_node |
Distribution layer for the id_effect Process Mesh: node identity, cookie handshake, and pluggable transports (InMemory/TCP/QUIC) | |
id_effect_process |
BEAM/OTP-style processes, links, monitors, and supervision trees for id_effect |
Integrations
| Crate | Version | Description |
|---|---|---|
id_effect_axum |
Axum and Tower integration for id_effect — Send-safe Effect handlers, request-scoped capabilities, host lifecycle | |
id_effect_cli |
CLI helpers for id_effect: optional clap, Exit/Cause → ExitCode, tracing buffer, run_main | |
id_effect_events |
Event sourcing, projections, and CQRS boundaries for id_effect programs | |
id_effect_opentelemetry |
OpenTelemetry tracing, metrics and logs integration for id_effect (OTLP export, propagation) | |
id_effect_platform |
Platform capability traits (HTTP, FS, subprocess commands) for id_effect — @effect/platform-style boundaries | |
id_effect_rpc_macros |
Procedural macros for id_effect_rpc: #[rpc::service] services with typed procedures, clients and contracts |
|
id_effect_sql |
Driver-agnostic SQL client traits for id_effect — @effect/sql-style boundaries | |
id_effect_tool |
The id-effect command: id-effect new scaffolds a service, worker, CLI or cluster node on id_effect_kit; id-effect migrate runs SQL migrations |
Platform (batteries)
| Crate | Version | Description |
|---|---|---|
id_effect_auth |
Authentication for id_effect services: password hashing, sessions, JWT, API-key and OIDC credentials | |
id_effect_authz |
Authorization for id_effect services: roles and permissions, named and resource policies, route guards | |
id_effect_console |
Operator console for id_effect services: live fibers, jobs and queues behind authorization guards | |
id_effect_jobs |
Background jobs for id_effect services: a Postgres SKIP LOCKED queue, workers, retries and cron | |
id_effect_kit |
One front door to id_effect: a single dependency with feature flags per battery and a prelude | |
id_effect_mail |
Outgoing mail for id_effect services: SMTP, the SendGrid API, templates and delivery through jobs | |
id_effect_messaging |
Messaging for id_effect services: a broker-agnostic MessageBroker, in-memory broker, outbox, inbox and relay | |
id_effect_redis |
Redis for id_effect services: pooled client layer, typed key-value, hash and JSON stores, a Cache backend, pub/sub streams, a Redis Streams message broker, sessions and rate limits | |
id_effect_rpc |
Typed RPC for id_effect: procedures with access decisions, a serde contract, HTTP dispatch and a Rust client (ADR 0014) | |
id_effect_storage |
Object storage for id_effect services: one store interface over file-system, in-memory and S3-compatible backends | |
id_effect_test |
Integration-test support for id_effect: effect-native containers, per-test database isolation, fixtures | |
id_effect_workflow |
Durable workflows for id_effect services: journaled steps replayed on resume, on id_effect_sql and id_effect_jobs |
Maintenance (frozen API)
| Crate | Version | Description |
|---|---|---|
id_effect_fp |
Functional-programming toolkit for id_effect: algebraic type classes, persistent collections, STM (maintenance tier) | |
id_effect_optics |
Functional optics — Lens, Prism, Traversal, JSON patch, and schema field paths for id_effect |
Labs (unpublished, no guarantees)
| Crate | Version | Description |
|---|---|---|
id_effect_ai |
unpublished | Vendor-neutral LLM client traits and streaming for id_effect |
id_effect_parse |
unpublished | Parser combinators, pretty printing, invertible codecs, and value diffs for id_effect |
Tiers and their quality bar: ADR 0010, docs/QUALITY_BAR.md.
Add the crate:
[dependencies]
id_effect = "0.13"use id_effect::{Effect, Never, succeed};
fn greet(name: &str) -> Effect<String, Never> {
succeed(format!("Hello, {name}!"))
}
fn main() {
let exit = greet("world").block_on();
println!("{exit:?}");
}For a guided path through the API, read Typed Effects in Rust first, then use the numbered examples under crates/id_effect/examples/ and docs.rs.
CLI template: examples/cli-minimal/ is the project template: clap + id_effect_cli + id_effect_config (Secret). Run:
devenv shell -- cargo run -p cli_minimal -- --token dummy| Resource | Link |
|---|---|
| Book (primary learning path) | Typed Effects in Rust — glossary |
CLI with clap + ExitCode |
CLI with clap (id_effect_cli) |
| API reference | docs.rs/id_effect |
| Examples | crates/id_effect/examples/ |
This repository uses devenv. Run commands inside the dev shell:
devenv shell -- <command>Common Moon tasks:
# Format
devenv shell -- moon run :format
# Check + clippy
devenv shell -- moon run :clippy
# Tests (nextest)
devenv shell -- moon run :test
# Coverage (96% threshold)
devenv shell -- moon run :coverage
# Build
devenv shell -- moon run :build
# Run examples for a crate
devenv shell -- moon run id_effect_lib:examples
# Security audit
devenv shell -- moon run :audit
# API docs + mdBook
devenv shell -- moon run :docs :book
# CI parity (same as GitHub moon-ci job)
devenv shell -- bash scripts/ci-local.sh affected
# Pre-push checks (ci-local + coverage + audit)
devenv shell -- pre-push| Workflow | Triggers | What it does |
|---|---|---|
| CI | push/PR → main |
Format, clippy, nextest, coverage (≥ 96 %), MSRV (1.94), Postgres integration, labs workspace, minimal versions, packaging, version drift, matrix (stable+beta × linux+mac+win) |
| Docs & Pages | push/PR → main |
API docs + mdBook → GitHub Pages |
| Security Audit | daily + Cargo.lock changes |
cargo audit |
| Publish | v*.*.* tag |
Test, package, SLSA Build L3 provenance and SBOMs, publish in dependency order, verify crates.io against the provenance, GitHub Release (docs/RELEASING.md) |
# 1. Bump [workspace.package] version in the root Cargo.toml (all crates inherit it;
# keep labs/Cargo.toml in lockstep) and move CHANGELOG "Unreleased" under the version.
# 2. bash scripts/validate-crate-packaging.sh # publish order + packaging check
# 3. Merge, then tag the merge commit with an annotated tag; CI publishes in dependency order
git tag -a v0.13.0 -m "v0.13.0"
git push origin v0.13.0The publish order has one source: scripts/validate-crate-packaging.sh --print-order. Labs crates are never published.
Publishing uses the CARGO_REGISTRY_TOKEN secret of the crates-io GitHub environment, which also creates new crates on their first publish; the full flow and the owner steps are in docs/RELEASING.md. CODECOV_TOKEN is optional for coverage uploads.
CI enforces ≥ 96% lines, regions, and functions via cargo llvm-cov nextest
(scripts/llvm-cov-nextest.sh).
Thanks to everyone who has contributed patches, reported issues, or improved the types.
This project is licensed under the MIT License from 0.8.0 onwards. Versions up to and including 0.7.0 were published under CC-BY-SA-4.0 and keep that license. Contributions require a DCO sign-off; see CONTRIBUTING.md.