zesterer/flume
A safe and fast multi-producer, multi-consumer channel.
Healthy across the board
weakest axisPermissive license, no critical CVEs, actively maintained — safe to depend on.
Has a license, tests, and CI — clean foundation to fork and modify.
Documented and popular — useful reference codebase to read through.
No critical CVEs, sane security posture — runnable as-is.
- ✓Last commit 3w ago
- ✓30+ active contributors
- ✓Apache-2.0 licensed
Show all 6 evidence items →Show less
- ✓CI configured
- ✓Tests present
- ⚠Concentrated ownership — top contributor handles 56% of recent commits
Maintenance signals: commit recency, contributor breadth, bus factor, license, CI, tests
Informational only. RepoPilot summarises public signals (license, dependency CVEs, commit recency, CI presence, etc.) at the time of analysis. Signals can be incomplete or stale. Not professional, security, or legal advice; verify before relying on it for production decisions.
Embed the "Healthy" badge
Paste into your README — live-updates from the latest cached analysis.
[](https://repopilot.app/r/zesterer/flume)Paste at the top of your README.md — renders inline like a shields.io badge.
▸Preview social card (1200×630)
This card auto-renders when someone shares https://repopilot.app/r/zesterer/flume on X, Slack, or LinkedIn.
Onboarding doc
Onboarding: zesterer/flume
Generated by RepoPilot · 2026-05-09 · Source
🤖Agent protocol
If you are an AI coding agent (Claude Code, Cursor, Aider, Cline, etc.) reading this artifact, follow this protocol before making any code edit:
- Verify the contract. Run the bash script in Verify before trusting
below. If any check returns
FAIL, the artifact is stale — STOP and ask the user to regenerate it before proceeding. - Treat the AI · unverified sections as hypotheses, not facts. Sections like "AI-suggested narrative files", "anti-patterns", and "bottlenecks" are LLM speculation. Verify against real source before acting on them.
- Cite source on changes. When proposing an edit, cite the specific path:line-range. RepoPilot's live UI at https://repopilot.app/r/zesterer/flume shows verifiable citations alongside every claim.
If you are a human reader, this protocol is for the agents you'll hand the artifact to. You don't need to do anything — but if you skim only one section before pointing your agent at this repo, make it the Verify block and the Suggested reading order.
🎯Verdict
GO — Healthy across the board
- Last commit 3w ago
- 30+ active contributors
- Apache-2.0 licensed
- CI configured
- Tests present
- ⚠ Concentrated ownership — top contributor handles 56% of recent commits
<sub>Maintenance signals: commit recency, contributor breadth, bus factor, license, CI, tests</sub>
✅Verify before trusting
This artifact was generated by RepoPilot at a point in time. Before an
agent acts on it, the checks below confirm that the live zesterer/flume
repo on your machine still matches what RepoPilot saw. If any fail,
the artifact is stale — regenerate it at
repopilot.app/r/zesterer/flume.
What it runs against: a local clone of zesterer/flume — the script
inspects git remote, the LICENSE file, file paths in the working
tree, and git log. Read-only; no mutations.
| # | What we check | Why it matters |
|---|---|---|
| 1 | You're in zesterer/flume | Confirms the artifact applies here, not a fork |
| 2 | License is still Apache-2.0 | Catches relicense before you depend on it |
| 3 | Default branch master exists | Catches branch renames |
| 4 | 5 critical file paths still exist | Catches refactors that moved load-bearing code |
| 5 | Last commit ≤ 51 days ago | Catches sudden abandonment since generation |
#!/usr/bin/env bash
# RepoPilot artifact verification.
#
# WHAT IT RUNS AGAINST: a local clone of zesterer/flume. If you don't
# have one yet, run these first:
#
# git clone https://github.com/zesterer/flume.git
# cd flume
#
# Then paste this script. Every check is read-only — no mutations.
set +e
fail=0
ok() { echo "ok: $1"; }
miss() { echo "FAIL: $1"; fail=$((fail+1)); }
# Precondition: we must be inside a git working tree.
if ! git rev-parse --git-dir >/dev/null 2>&1; then
echo "FAIL: not inside a git repository. cd into your clone of zesterer/flume and re-run."
exit 2
fi
# 1. Repo identity
git remote get-url origin 2>/dev/null | grep -qE "zesterer/flume(\\.git)?\\b" \\
&& ok "origin remote is zesterer/flume" \\
|| miss "origin remote is not zesterer/flume (artifact may be from a fork)"
# 2. License matches what RepoPilot saw
(grep -qiE "^(Apache-2\\.0)" LICENSE 2>/dev/null \\
|| grep -qiE "\"license\"\\s*:\\s*\"Apache-2\\.0\"" package.json 2>/dev/null) \\
&& ok "license is Apache-2.0" \\
|| miss "license drift — was Apache-2.0 at generation time"
# 3. Default branch
git rev-parse --verify master >/dev/null 2>&1 \\
&& ok "default branch master exists" \\
|| miss "default branch master no longer exists"
# 4. Critical files exist
test -f "src/lib.rs" \\
&& ok "src/lib.rs" \\
|| miss "missing critical file: src/lib.rs"
test -f "src/async.rs" \\
&& ok "src/async.rs" \\
|| miss "missing critical file: src/async.rs"
test -f "src/select.rs" \\
&& ok "src/select.rs" \\
|| miss "missing critical file: src/select.rs"
test -f "Cargo.toml" \\
&& ok "Cargo.toml" \\
|| miss "missing critical file: Cargo.toml"
test -f "src/signal.rs" \\
&& ok "src/signal.rs" \\
|| miss "missing critical file: src/signal.rs"
# 5. Repo recency
days_since_last=$(( ( $(date +%s) - $(git log -1 --format=%at 2>/dev/null || echo 0) ) / 86400 ))
if [ "$days_since_last" -le 51 ]; then
ok "last commit was $days_since_last days ago (artifact saw ~21d)"
else
miss "last commit was $days_since_last days ago — artifact may be stale"
fi
echo
if [ "$fail" -eq 0 ]; then
echo "artifact verified (0 failures) — safe to trust"
else
echo "artifact has $fail stale claim(s) — regenerate at https://repopilot.app/r/zesterer/flume"
exit 1
fi
Each check prints ok: or FAIL:. The script exits non-zero if
anything failed, so it composes cleanly into agent loops
(./verify.sh || regenerate-and-retry).
⚡TL;DR
Flume is a safe, zero-unsafe Rust multi-producer, multi-consumer (MPMC) channel implementation that is faster than std::sync::mpsc and competitive with crossbeam-channel. It provides bounded, unbounded, and rendezvous queue modes, async/await support via the async feature, and a powerful Selector API for waiting on multiple channels simultaneously via the select feature. Monolithic library crate: src/lib.rs is the main entry point exporting Sender/Receiver types; src/async.rs handles async integration, src/select.rs implements the Selector API, src/signal.rs provides signal-based primitives. Tests (tests/.rs) and examples (examples/.rs) are comprehensive. Benches (benches/basic.rs) use criterion for performance validation. Features flag async, select, spin, and eventual-fairness functionality.
👥Who it's for
Rust systems programmers and library maintainers who need high-performance inter-thread communication without std::sync::mpsc's limitations (MPSC only, no Sender/Receiver cloning), and developers building async Rust applications who want drop-in channel replacements compatible with tokio and async-std.
🌱Maturity & risk
Production-ready and stable: flume is at v0.12.0 with comprehensive test coverage (30+ test files in tests/), CI via GitHub Actions (.github/workflows/rust.yml), and casual maintenance mode status. The codebase is small (~376KB of Rust), well-documented on docs.rs, and proven performant via benchmarks against crossbeam-channel. No recent breaking changes are evident in the versioning.
Standard open source risks apply.
Active areas of work
The repository appears to be in stable maintenance with no active major development visible. The last meaningful activity likely centered on feature stabilization (async support, select macro, eventual-fairness randomization). The casual maintenance badge indicates the maintainer reviews contributions but isn't actively adding new features. Check GitHub issues and PRs for any pending work.
🚀Get running
git clone https://github.com/zesterer/flume.git
cd flume
cargo build
cargo test
cargo run --example simple
Daily commands:
For sync usage: cargo run --example simple. For async: cargo run --example async --features async. For select: cargo run --example select --features select. For performance profiling: cargo bench --bench basic. All examples compile with cargo build --examples.
🗺️Map of the codebase
src/lib.rs— Core entry point defining Sender, Receiver, and the primary channel creation API—all contributing developers must understand the type signatures and threading guarantees exported here.src/async.rs— Implements async/await support via futures traits—essential for async feature users and anyone extending async channel behavior.src/select.rs— Implements the select! macro for multiplexing across multiple channels—critical for understanding Flume's sophisticated blocking strategy.Cargo.toml— Defines all feature flags (async, select, eventual-fairness, spin) that gate major architectural choices—contributors must understand how features compose.src/signal.rs— Low-level notification primitive underlying the channel's thread-safe blocking mechanism—foundational for understanding wakeup semantics.benches/basic.rs— Performance benchmarks that validate the 'blazingly fast' claim—contributors should run these to catch regressions.tests/basic.rs— Core integration tests for bounded, unbounded, and rendezvous channels—defines expected behavior contract.
🧩Components & responsibilities
- Sender (Arc<Channel>, Mutex/Spinlock) — Pushes messages into the queue, potentially unparking waiting receivers; implements Clone and Send+Sync; transparent to bounded vs unbounded distinction
- Failure mode: Sending to a closed channel returns SendError; unsynchronized clone() could cause data races (prevented by type system)
- Receiver (Arc<Channel>, Signal/Wakeup, Optional Future impl) — Pulls messages from the queue, parking thread if empty; implements Clone, Send+Sync, Iterator, futures::Stream
- Failure mode: Receiving on a closed empty channel returns RecvError; concurrent recv() calls may race (handled by queue lock)
- Internal Queue (bounded/unbounded/rendezvous) (VecDeque (unbounded), ringbuffer (bounded), wait-queue (rendezvous)) — FIFO message buffer; different capacity policies; protected by shared Mutex or Spinlock
- Failure mode: Buffer overflow (unbounded, only OOM); deadlock if rendezvous producer/consumer misaligned; lock contention under high throughput
- Signal (Wakeup primitive) (std::sync primitives,) — Coordinates thread parking/unparking between senders and receivers; tracks waiter count to avoid spurious wakeups
🛠️How to make changes
Add a new channel queue strategy (bounded vs unbounded vs rendezvous variant)
- Extend the internal queue abstraction in src/lib.rs by adding a new queue type (e.g., PriorityQueue wrapping the existing queue logic) (
src/lib.rs) - Add a factory function (e.g., priority()) exporting the new channel variant (
src/lib.rs) - Write integration tests in tests/basic.rs validating queue ordering and bounds behavior (
tests/basic.rs) - Add a micro-benchmark in benches/basic.rs to compare performance against existing strategies (
benches/basic.rs)
Extend select!() macro with new channel types or predicates
- Study the existing select!() implementation and proc-macro patterns in src/select.rs (
src/select.rs) - Modify src/select.rs to handle new branch conditions (e.g., timeout branches, conditional sends) (
src/select.rs) - Add test cases demonstrating the new select!() syntax in tests/select.rs or tests/select_macro.rs (
tests/select_macro.rs) - Update the example in examples/select.rs to showcase the new capability (
examples/select.rs)
Add a new async runtime backend (beyond futures/tokio)
- Review the futures-trait integration in src/async.rs and identify the abstraction boundary (
src/async.rs) - Create a feature flag in Cargo.toml (e.g., smol-backend) gating the new runtime adapter (
Cargo.toml) - Implement the new runtime adapter in src/async.rs (or a new file src/async_smol.rs) following the existing Future trait pattern (
src/async.rs) - Add comprehensive async tests in tests/async.rs validating the new backend with both send/recv and select scenarios (
tests/async.rs)
🔧Why these technologies
- Rust with no unsafe — Guarantees memory safety and data-race freedom at compile time; aligns with 'Safe' marketing claim and prevents entire categories of concurrency bugs.
- futures-core/futures-sink traits — Provides async/await support via standard Rust ecosystem interfaces; decouples from specific async runtimes (tokio, async-std, smol).
- select!() macro (proc-macro style) — Enables ergonomic multiplexing across multiple channels, matching Go's channel select semantics; eventual-fairness feature prevents starvation.
- Spinlock option (spin feature) — Allows tuning for high-contention scenarios where std::sync::Mutex overhead is unacceptable; disabled by default for general fairness.
⚖️Trade-offs already made
-
Unbounded channels with dynamic allocation vs. bounded channels with fixed queues
- Why: Unbounded channels offer flexibility but risk memory exhaustion; bounded channels enforce backpressure but require producer coordination.
- Consequence: API surface exposes all three modes (bounded, unbounded, rendezvous); users must choose based on their threat model.
-
No unsafe code anywhere (safe-first approach)
- Why: Maximizes correctness and auditability; simplifies contribution guidelines; sells on safety claim.
- Consequence: May sacrifice micro-optimizations only possible with unsafe (e.g., raw pointer tricks); performance is still competitive via algorithmic efficiency.
-
Features (async, select, eventual-fairness) are all default-enabled
- Why: Batteries-included approach provides best experience for most users; select! is rarely a performance burden.
- Consequence: Larger binary footprint and compile time for users who only need basic MPMC; users must explicitly opt-out.
-
Thread-local storage for eventual-fairness (fastrand-based random selection)
- Why: Prevents select!() starvation when many branches are ready; avoids global RNG contention.
- Consequence: Adds thread_locals dependency and slight per-channel overhead; fairness not guaranteed under pathological load.
🚫Non-goals (don't propose these)
- Distributed channels across process boundaries (single-machine only)
- Priority queues or message ordering beyond FIFO
- Built-in request-response patterns (use external RPC libraries)
- Structured concurrency or cancellation tokens (design for compatibility with external cancel libs)
- Persistent/durable queuing (in-memory only; no durability)
🪤Traps & gotchas
- Feature interdependencies:
eventual-fairnessimplicitly requiresselect; compile withcargo build --features eventual-fairnesswill auto-enable select. - Spin vs OS locks:spinfeature changes internal locking behavior; benchmark-sensitive code may regress if enabled on high-contention platforms. - Async without async feature: calling Sender::send_async() withoutasyncfeature enabled will fail compilation; ensure feature flags in Cargo.toml match usage. - MSRV 1.78.0: code uses patterns (e.g., Edition 2018 syntax) that require Rust 1.78.0+; older toolchains will fail silently. - No runtime required for sync: sync channels work bare-metal; async channels require a runtime (tokio, async-std, or custom executor).
🏗️Architecture
💡Concepts to learn
- Multi-Producer Multi-Consumer (MPMC) — Flume's core differentiator from std::sync::mpsc (which is MPSC-only); MPMC requires shared queue state and atomic coordination that flume implements without unsafe code
- Lock-Free Data Structures / Wait-Free Synchronization — Flume achieves high performance through minimal locking; understanding spinlocks (via
spinfeature) vs OS primitives is key to performance tuning decisions - Interior Mutability Pattern — Flume wraps queue state in Arc<Mutex<>> or Arc<RwLock<>>; understanding when to use Mutex vs RwLock vs spinlocks is crucial for modifying the core implementation
- Futures Trait and Pinning — The
asyncfeature implements Future::poll() manually; contributors to async.rs must understand Pin stability and waker mechanics to avoid soundness bugs - Rendezvous Channels / Synchronous Handoff — Flume supports 0-capacity bounded channels (rendezvous mode) where sender and receiver block until both are ready; this pattern is used for strict coordination in distributed systems
- Eventual Fairness via Randomization — The
eventual-fairnessfeature uses fastrand to avoid Selector bias toward high-throughput channels; understanding how randomization prevents starvation is key to understanding the select implementation - Arc-Based Shared Ownership — Both Sender and Receiver are Arc<inner> clones that keep the queue alive until all handles drop; this design enables safe cloning and is central to flume's ergonomics vs std::sync::mpsc
🔗Related repos
crossbeam-rs/crossbeam-channel— Direct competitor: mature MPMC channel used in benchmarks against flume; crossbeam-channel uses unsafe for performance, flume uses zero unsafe by designrust-lang/rust— Home of std::sync::mpsc: flume is designed as a drop-in replacement with MPMC support and better performance than stdlibtokio-rs/tokio— Primary async runtime that flume integrates with; tokio users adopt flume for channels that work across sync and async contextsasync-rs/async-std— Alternative async runtime supported by flume; tests/async.rs uses async-std for integration validationzesterer/veloren— Large real-world Rust project (voxel game) that likely uses flume for inter-system communication; demonstrates production viability
🪄PR ideas
To work on one of these in Claude Code or Cursor, paste:
Implement the "<title>" PR idea from CLAUDE.md, working through the checklist as the task list.
Add comprehensive benchmarks comparing Flume with crossbeam-channel across feature configurations
The repo includes crossbeam-channel as a dev-dependency and has benches/basic.rs, but lacks detailed comparative benchmarks. With multiple feature combinations (spin, select, async, eventual-fairness), contributors could add criterion benchmarks that systematically compare Flume's performance variants against crossbeam-channel across different workload patterns (bounded/unbounded, contention levels, throughput/latency). This would validate the 'blazingly fast' claim in the README and provide concrete performance data for feature trade-offs.
- [ ] Create benches/comparison.rs with criterion benchmarks
- [ ] Add benchmarks for bounded and unbounded channels with varying capacities
- [ ] Add benchmarks comparing Flume with/without spin, select, and eventual-fairness features against crossbeam-channel
- [ ] Add benchmarks for multi-producer and multi-consumer contention scenarios
- [ ] Document benchmark results in a new BENCHMARKS.md file
Add integration tests for async cancellation safety and waker edge cases in src/async.rs
The async feature (src/async.rs) depends on futures-sink and futures-core but tests/async.rs coverage appears limited. Given that async channel cancellation and waker behavior are subtle and error-prone, a new comprehensive test file should verify: proper cleanup on receiver drop, waker behavior across select operations, and interaction with tokio/async-std runtimes. This directly impacts safety claims and prevents regression in async codepaths.
- [ ] Create tests/async_cancellation.rs for drop safety during pending operations
- [ ] Add tests verifying waker de-duplication and correctness in src/async.rs flows
- [ ] Add tests for waker behavior in select! macro context (tests/select_macro.rs integration)
- [ ] Add stress tests with tokio and async-std to verify runtime compatibility
- [ ] Test timeout and cancellation patterns using tokio::time::timeout
Implement feature-gated MIRI validation tests for memory safety under eventual-fairness
The eventual-fairness feature adds fastrand dependency for non-deterministic scheduling fairness in select! operations. This introduces subtle concurrency behavior that's difficult to validate. Adding MIRI (Miri interpreter for detecting undefined behavior) tests under a feature flag would catch memory safety issues that standard testing may miss. The src/select.rs file would particularly benefit from this validation.
- [ ] Create tests/miri_validation.rs with #[cfg(miri)] guards
- [ ] Add test cases exercising src/select.rs with eventual-fairness enabled under MIRI
- [ ] Add test cases for concurrent sender/receiver with spin feature enabled
- [ ] Update .github/workflows/rust.yml to run MIRI tests: 'cargo +nightly miri test --features eventual-fairness'
- [ ] Document MIRI testing process in CONTRIBUTING.md or similar
🌿Good first issues
- Add a test file
tests/perf_comparison.rsthat benchmarks flume::unbounded against std::sync::mpsc with identical workloads and documents performance ratios in results; this validates the README's speed claims and provides regression detection. - Create an example
examples/bounded_backpressure.rsdemonstrating bounded channel backpressure handling and spawning multiple senders/receivers; pair it with documentation in README under 'Advanced Usage'. - Add missing edge-case tests to
tests/basic.rsfor Sender/Receiver behavior after Channel is closed (drop before send/recv, cloned handle behavior, error propagation); currently coverage is incomplete for all drop orderings.
⭐Top contributors
Click to expand
Top contributors
- @zesterer — 56 commits
- @white-axe — 4 commits
- @rumpuslabs — 3 commits
- @tontinton — 3 commits
- @lucaato — 2 commits
📝Recent commits
Click to expand
Recent commits
f5a85c7— Merge pull request #179 from rumpuslabs/empty-select (zesterer)ae00785— fix: explicit panic on empty Selector (rumpuslabs)dddc30a— Merge pull request #178 from CosminPerRam/msrv (zesterer)ad048bf— feat: add rust-version to Cargo.toml (CosminPerRam)58e0c09— Updated changelog, bumped version (zesterer)a26973d— Merge pull request #171 from tontinton/clippy (zesterer)e3392f7— lint tests in CI (tontinton)c747552— fmt (tontinton)43a1129— fix clippy lints (tontinton)6d9b220— fmt (zesterer)
🔒Security observations
The flume codebase demonstrates strong security practices overall. As a low-level concurrency library written in Rust, it benefits from memory safety guarantees. No critical vulnerabilities were identified in the dependency tree or file structure. The main concerns are minor: use of a forked 'spin' crate instead of the official one, and optional JavaScript feature dependencies. The codebase lacks the common injection attack vectors (SQL, XSS) typical of web applications, and no hardcoded secrets or exposed credentials were found. The project maintains good practices with dual MIT/Apache-2.0 licensing and CI/CD via GitHub Actions.
- Low · Dependency on Unmaintained 'spin' Crate Fork —
Cargo.toml - dependencies section. The codebase uses 'spin1' (version 0.9.8), which is a fork of the 'spin' crate. Using forks instead of the official crate can lead to missing security updates and maintenance. The original 'spin' crate may have security patches that don't get applied to the fork. Fix: Evaluate whether the fork is necessary. If possible, migrate back to the official 'spin' crate (https://crates.io/crates/spin) to ensure timely security updates. - Low · Transitive Dependency Risk from 'fastrand' —
Cargo.toml - fastrand dependency with 'std' and 'js' features. The 'fastrand' crate (2.3.x) is used as an optional dependency for 'eventual-fairness' feature. While fastrand is a reputable crate, it's a JavaScript-related feature that could introduce unexpected dependencies. The 'js' feature flag increases attack surface for web-based use cases. Fix: Monitor fastrand crate for security updates. Consider whether the 'js' feature is actually needed for your use cases. Keep the dependency updated regularly.
LLM-derived; treat as a starting point, not a security audit.
👉Where to read next
- Open issues — current backlog
- Recent PRs — what's actively shipping
- Source on GitHub
Generated by RepoPilot. Verdict based on maintenance signals — see the live page for receipts. Re-run on a new commit to refresh.