AetherFlow
Flow at the speed of hardware.
A high-performance actor runtime for Rust — thread-per-core, lock-free, zero-copy. The type system proves isolation at compile time, which unlocks optimizations other runtimes can't safely make.
Docs · Why AetherFlow? · Benchmarks
AetherFlow is not a Tokio replacement. It's a different lineage: an actor runtime designed from the CPU up — cores, caches, and message ownership are first-class, not afterthoughts.
You write plain typed Rust. When you send a message, its ownership is
moved into the runtime — using it afterward doesn't compile (E0382). This is
Pony's iso idea recovered in Rust as a moved T: Send, so the runtime routes
the message without locks, without GC, and with no per-message Arc/refcount —
guarantees, not benchmarks. (Ownership of the message value is transferred; Rust's
Send still lets you put explicitly-shared state like Arc<Mutex<_>> inside a
message if you choose — see Known limitations.)
- 🛡️ Isolation, proven at compile time — data-race freedom is a type error,
not a runtime convention. Use-after-send doesn't compile (
E0382). - ⚡ Thread-per-core, run-to-completion — one OS thread per core, actors pinned, no work-stealing, no cross-core migration. Cache locality by construction.
- 📨 Zero-copy messages —
sendmoves ownership. No clone, noArc<Mutex>. - 🔒 Lock-free mailboxes — bounded MPSC ring, head/tail on separate cache lines to avoid false sharing.
- 🎯 The whole triple, at once — static data-race-free + zero-GC-pause +
no per-message heap alloc, clone, or
Arcrefcount. (The lock-free mailbox uses atomics like any MPSC — what's absent is per-message refcounting, not all atomics.) Pony proved capabilities but pays GC; other Rust actor frameworks have neither.
Quick start
[]
= "0.1"
use ;
// An actor is plain typed Rust: one message type, one handler.
Heads-up:
with_cores(n)defaults toIdleStrategy::BusySpin— lowest latency, but it keepsncores at ~100% CPU. On a laptop or shared box, useSystem::with_cores_idle(n, IdleStrategy::backoff()).
Need a reply? ask puts the reply cell on the call stack — no per-call heap
allocation (the caller blocks until the actor replies):
let depth: u64 = book.ask?;
Why "the type system unlocks the speed"
Performance mechanisms — batching, per-core pools, emplace — are a treadmill: anyone copies your numbers in one release. Speed alone is not a moat.
The moat is the type system. Because the message value is moved (single-owned at the message boundary, checked at compile time), aggressive optimizations — no per-message atomic refcount, no GC, per-core message reuse — become structurally safe. A runtime without a type system can't copy them safely; it would have to build the type system too (Pony-scale cost).
And you never write a capability annotation. The theory works under the floor; on the surface you write ordinary Rust and the guarantees come free. That's the design principle: deep theory, shallow surface. See design.md §2.4–2.6.
Status & scope
Single-node v1. This is a systems project under active development.
- ✅ typed actors · move messages · lock-free MPSC mailbox · thread-per-core ·
core pinning (best-effort) · zero-alloc
ask - ✅ Tail latency validated on real hardware — on AWS Graviton3 (real Linux,
native core pinning) the busy-spin tail collapses from milliseconds to ~3–5µs,
and AetherFlow wins every percentile vs Tokio (median ~10×, p99 ~13×, p999
~3–4.5×). Zero-alloc
askruns sub-µs (p50 268ns / p999 399ns). Core pinning is a no-op on macOS (an OS limitation, not ARM). See benchmarks. - 🎯 Next: isolated cores (isolcpus/nohz_full, bare metal) to drive p99.9 into single-digit µs — matching-engine / HFT territory.
- 🧊 Frozen for now: distributed, clustering, persistence, and streams. These are on the roadmap, not the current build. See direction & roadmap.
Not for elite HFT (they build their own or go FPGA). The target is the tier that wants Disruptor-class speed with safety and productivity but has no HFT team: exchanges, brokers, real-time risk, market data, ad RTB, game tick servers.
Known limitations (honest scope for 0.1)
This is a young systems project. The concept and core are solid, but several correctness/robustness items are deliberately not done yet — we'd rather state them than have you discover them:
- Isolation is at the message boundary, not deep.
sendmoves the message value (use-after-send isE0382), but Rust'sSenddoesn't forbid explicitly shared internals — a message can still carryArc<Mutex<_>>if you write it that way. This is ownership transfer, not Pony-iso-strength deep uniqueness. askliveness depends on the callee replying. If the actor is already gone when youask, you getErr(AskError::Closed). But the reply cell lives on the caller's stack, so if an actor stores theResponderinstead of replying, the caller blocks. Generation-tagged reply slots are on the roadmap.- Lock-free queue verification. Concurrent tests plus a Miri UB check on the single-threaded unsafe paths pass today; exhaustive interleaving verification (Loom) is on the roadmap before 1.0.
IdleStrategy::BusySpinis the default (100% CPU per core) — useIdleStrategy::backoff()on shared or battery-powered machines.
Documentation
- design.md — the technical thesis (four pillars) and prior art (Pony / LMAX)
- direction-and-roadmap.md — why this shape, and the path forward
- competitive-landscape.md — how it differs from glommio / kompact / Pony
- concepts-explained.md — plain-language glossary
- pony-rust-capability-mapping.md — Pony capabilities ⇄ Rust ownership
Contributing
AetherFlow is open source and contributions are welcome — bug reports, feature requests, and pull requests alike. See CONTRIBUTING.md.
License
Licensed under either of
- Apache License, Version 2.0 (LICENSE-APACHE)
- MIT license (LICENSE-MIT)
at your option. Unless you explicitly state otherwise, any contribution intentionally submitted for inclusion in the work by you, as defined in the Apache-2.0 license, shall be dual licensed as above, without any additional terms or conditions.