Course contentsShow
← Rust
Lesson 1117 of 1,91010. Concurrency PrimitivesFree lesson

Backpressure and Throughput Control

You will manage system health by using bounded buffers to slow down aggressive producers.

In this lesson, you will learn how to maintain system stability by using bounded buffers to exert backpressure, preventing aggressive producers from overwhelming your consumers.

The Problem of Unbounded Growth

When you use an unbounded channel (like std::sync::mpsc::channel()), you essentially create a bottomless pit for data. If a producer is significantly faster than the consumer, the channel's internal memory usage will grow indefinitely until your application crashes due to an Out-of-Memory (OOM) error. This is a classic "thundering herd" or "runaway producer" scenario that undermines system health.

Implementing Backpressure

Backpressure is the technique of signaling a producer to slow down once the consumer can no longer keep up. In Rust, we achieve this through bounded channels. By using std::sync::mpsc::sync_channel(bound), we define a fixed capacity for the buffer.

When the buffer reaches its limit, the send() method blocks the producer thread, effectively forcing it to wait until the consumer makes space by processing a message. This automatically synchronizes the producer’s throughput with the consumer’s processing speed.

use std::sync::mpsc::sync_channel;
use std::thread;
use std::time::Duration;

fn main() {
    // A channel with a buffer size of 2
    let (tx, rx) = sync_channel(2);

    thread::spawn(move || {
        for i in 0..10 {
            println!("Producing: {}", i);
            // This will block once 2 messages are waiting in the queue
            tx.send(i).unwrap();
        }
    });

    for received in rx {
        println!("Consuming: {}", received);
        // Simulate slow processing
        thread::sleep(Duration::from_millis(500));
    }
}

Why This Works

In the example above, even though the producer wants to send 10 items instantly, the sync_channel(2) acts as a throttle. The producer is suspended by the operating system scheduler the moment it tries to send the third message. It remains in a wait state until the consumer finishes its sleep and pulls a message out of the queue. By coupling the threads' execution speeds to the buffer state, you transform an unstable, explosive system into a steady, predictable pipeline.

Key Takeaway: Use bounded channels to create natural, thread-blocking backpressure that forces fast producers to align their throughput with your consumer's actual capacity.