How to Build a Backpressure Generator Pause Producer Demo in Python
Demonstrates a producer–consumer pattern with a fixed-size buffer that pauses production when full, simulating backpressure.
Python code
27 linesimport time
import collections
def producer(buffer, max_size, items):
"""Adds items to the buffer until full, then pauses."""
for item in items:
while len(buffer) >= max_size:
print(f"Buffer full ({len(buffer)}/{max_size}) — producer paused")
time.sleep(0.1)
buffer.append(item)
print(f"Produced: {item} (buffer size: {len(buffer)})")
def consumer(buffer):
"""Consumes one item per call."""
if buffer:
item = buffer.popleft()
print(f"Consumed: {item} (buffer size: {len(buffer)})")
return item
return None
if __name__ == "__main__":
buffer = collections.deque(maxlen=3)
items = ["a", "b", "c", "d", "e", "f"]
producer(buffer, buffer.maxlen, items)
for _ in range(len(items)):
consumer(buffer)
Output
Produced: a (buffer size: 1)
Produced: b (buffer size: 2)
Produced: c (buffer size: 3)
Buffer full (3/3) — producer paused
Buffer full (3/3) — producer paused
Produced: d (buffer size: 3)
Buffer full (3/3) — producer paused
Buffer full (3/3) — producer paused
Produced: e (buffer size: 3)
Buffer full (3/3) — producer paused
Buffer full (3/3) — producer paused
Produced: f (buffer size: 3)
Consumed: a (buffer size: 2)
Consumed: b (buffer size: 1)
Consumed: c (buffer size: 0)
Consumed: d (buffer size: 2)
Consumed: e (buffer size: 1)
Consumed: f (buffer size: 0)
How it works
The producer function uses a while loop to check whether the buffer has reached max_size, pausing with time.sleep(0.1) when full. collections.deque(maxlen=3) enforces the buffer capacity, automatically dropping oldest items if you bypass the size check. The consumer pops items from the left side, simulating FIFO processing. This pattern mirrors real backpressure handling where a slow consumer forces the producer to wait.
Common mistakes
- Using `deque(maxlen=3)` without checking fullness—silently drops items instead of pausing
- Calling `len(buffer)` repeatedly in a tight loop without a sleep, causing high CPU usage
- Not clearing the buffer before reuse, leading to unexpected state between runs
Variations
- Replace `time.sleep` with `asyncio.sleep` in an async producer for non-blocking backpressure
- Use a threading.Event or queue.Queue with `put` blocking to coordinate producer and consumer threads
Real-world use cases
- Rate-limiting API requests when the response queue backs up during high-load bursts.
- Building a video streaming pipeline where the encoder pauses when downstream decoder buffers fill.
- Managing a job queue where producers wait until workers catch up to prevent memory exhaustion.
Sponsored
More from Comprehensions & generators
- Batch Rows in Chunks with a Generator in Python easy
- Build a Generator Pipeline in Python: Filter Then Map medium
- Build a lazy generator to read file lines in Python easy
- Chunk an Iterable into Batches with a Generator in Python easy
- Convert Data in Python with Comprehensions and Generators easy
- Count Data in Python with Comprehensions and Generators easy
Keep learning
Related tutorials and quizzes for this topic.