RepoPilotOpen in app →

zesterer/flume

A safe and fast multi-producer, multi-consumer channel.

Healthy

Healthy across the board

weakest axis
Use as dependencyHealthy

Permissive license, no critical CVEs, actively maintained — safe to depend on.

Fork & modifyHealthy

Has a license, tests, and CI — clean foundation to fork and modify.

Learn fromHealthy

Documented and popular — useful reference codebase to read through.

Deploy as-isHealthy

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 →
  • 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.

Variant:
RepoPilot: Healthy
[![RepoPilot: Healthy](https://repopilot.app/api/badge/zesterer/flume)](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:

  1. 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.
  2. 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.
  3. 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 |

<details> <summary><b>Run all checks</b> — paste this script from inside your clone of <code>zesterer/flume</code></summary>
#!/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).

</details>

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)

  1. 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)
  2. Add a factory function (e.g., priority()) exporting the new channel variant (src/lib.rs)
  3. Write integration tests in tests/basic.rs validating queue ordering and bounds behavior (tests/basic.rs)
  4. 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

  1. Study the existing select!() implementation and proc-macro patterns in src/select.rs (src/select.rs)
  2. Modify src/select.rs to handle new branch conditions (e.g., timeout branches, conditional sends) (src/select.rs)
  3. Add test cases demonstrating the new select!() syntax in tests/select.rs or tests/select_macro.rs (tests/select_macro.rs)
  4. Update the example in examples/select.rs to showcase the new capability (examples/select.rs)

Add a new async runtime backend (beyond futures/tokio)

  1. Review the futures-trait integration in src/async.rs and identify the abstraction boundary (src/async.rs)
  2. Create a feature flag in Cargo.toml (e.g., smol-backend) gating the new runtime adapter (Cargo.toml)
  3. 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)
  4. 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-fairness implicitly requires select; compile with cargo build --features eventual-fairness will auto-enable select. - Spin vs OS locks: spin feature changes internal locking behavior; benchmark-sensitive code may regress if enabled on high-contention platforms. - Async without async feature: calling Sender::send_async() without async feature 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 spin feature) 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 async feature 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-fairness feature 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
  • 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 design
  • rust-lang/rust — Home of std::sync::mpsc: flume is designed as a drop-in replacement with MPMC support and better performance than stdlib
  • tokio-rs/tokio — Primary async runtime that flume integrates with; tokio users adopt flume for channels that work across sync and async contexts
  • async-rs/async-std — Alternative async runtime supported by flume; tests/async.rs uses async-std for integration validation
  • zesterer/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.rs that 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.rs demonstrating 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.rs for 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

📝Recent commits

Click to expand
  • 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.


Generated by RepoPilot. Verdict based on maintenance signals — see the live page for receipts. Re-run on a new commit to refresh.

Healthy signals · zesterer/flume — RepoPilot