DEV Community

Cover image for Implementing Adaptive Backpressure in Rust with FlowGuard
Cleiton Augusto
Cleiton Augusto

Posted on

Implementing Adaptive Backpressure in Rust with FlowGuard

Implementing Adaptive Backpressure in Rust with FlowGuard
Hey fellow Rustaceans! πŸ‘‹

I recently open-sourced FlowGuard, a library for adaptive concurrency control and backpressure in Rust services. In this post, I'll share why static rate limiting fails and how FlowGuard solves it with TCP Vegas congestion control.

πŸ€” The Problem with Static Limits
We've all done this:

rust
// "Maximum 100 concurrent connections"
let max_connections = 100;
But static limits are a trap:

Set too high? Your system crashes before reaching the limit

Set too low? You waste resources and refuse legitimate traffic

Guessing game? You're always tuning based on hunches

πŸš€ The Solution: Dynamic Backpressure
Instead of guessing, what if your system could self-adjust based on real-time performance? That's where FlowGuard comes in.

Introducing FlowGuard
FlowGuard implements the TCP Vegas congestion control algorithm to dynamically adjust concurrency limits based on actual system latency.

🎯 How It Works
rust
use flow_guard::{FlowGuard, VegasStrategy};
use std::sync::Arc;

[tokio::main]

async fn main() {
// Start with 10 concurrent operations
let strategy = Arc::new(VegasStrategy::new(10));
let guard = FlowGuard::new(Arc::clone(&strategy));

println!("Initial limit: {}", guard.current_limit());

// Execute tasks with adaptive backpressure
let result = guard.run(async {
    // Your database query, API call, etc.
    tokio::time::sleep(std::time::Duration::from_millis(100)).await;
    Ok::<_, &str>("Success!")
}).await;

println!("Final limit: {}", guard.current_limit()); // Adjusted!
Enter fullscreen mode Exit fullscreen mode

}
✨ Key Features

  1. Real-time Adjustment rust // Watch limits adjust dynamically println!("Current limit: {}", guard.current_limit()); println!("Available permits: {}", guard.available_permits());
  2. Vegas Algorithm Based on the difference between expected and actual throughput:

βœ… Increases limit when system has spare capacity

βœ… Decreases limit when latency indicates congestion

βœ… Self-tuning - no manual configuration needed

  1. Web Framework Integration rust // Axum 0.8 middleware let strategy = VegasStrategy::new(50); let flow_layer = FlowGuardLayer::new(strategy);

let app = Router::new()
.route("/api/data", get(handler))
.layer(flow_layer);
πŸ“¦ Getting Started
Add to your Cargo.toml:

toml
[dependencies]
flow-guard = "0.2.1"

With Axum/Tower support

flow-guard = { version = "0.2.1", features = ["axum", "tower"] }
πŸ”§ Under the Hood
FlowGuard replaces tokio::sync::Semaphore with a custom DynamicSemaphore that can adjust its limit up and down in real-time:

rust
pub struct DynamicSemaphore {
max_permits: AtomicUsize,
available_permits: AtomicUsize,
notify: Notify,
}

impl DynamicSemaphore {
pub fn set_limit(&self, new_limit: usize) {
// Adjusts permits dynamically based on Vegas calculations
}
}
🎯 Use Cases

  1. Database Protection rust // Prevent database overload let db_guard = FlowGuard::new(VegasStrategy::new(20));

async fn query_database() -> Result {
db_guard.run(|| async {
// Your database query here
database.query("SELECT * FROM users").await
}).await``
}

  1. API Rate Limiting rust // Adaptive rate limiting for external APIs let api_guard = FlowGuard::new(VegasStrategy::new(5));

async fn call_external_api() -> Result {
api_guard.run(|| async {
client.get("https://api.example.com/data").await
}).await
}

  1. Microservices rust // Protect services from cascading failures let service_guard = FlowGuard::new(VegasStrategy::new(100)); πŸ“Š Benchmarks In testing, FlowGuard showed:

5 β†’ 12 limit adjustment under optimal conditions

Sub-millisecond overhead per request

Zero allocation in hot path

Thread-safe with atomic operations

πŸš€ Try It Yourself
bash

Clone and run examples

git clone https://github.com/cleitonaugusto/flow-guard
cd flow-guard
cargo run --example basic_usage
πŸ”— Resources
GitHub: https://github.com/cleitonaugusto/flow-guard

Crates.io: https://crates.io/crates/flow-guard

Documentation: https://docs.rs/flow-guard/0.2.1/

Examples: basic_usage.rs, server_demo.rs

πŸ’­ Why I Built This
After seeing too many services crash from static limits or waste resources with conservative settings, I wanted a solution that adapts to actual system performance. The TCP Vegas algorithm has been battle-tested for decades in networking - why not apply it to service concurrency?

🀝 Contributing & Feedback
FlowGuard is open source under MIT license. I'd love your:

Feedback on the API design

Use cases from your projects

Contributions to the codebase

Ideas for improvements

What adaptive concurrency patterns have you used in your Rust projects? Share in the comments!

Top comments (0)