Backpressure
Backpressure is flow control that makes a producer adjust how much or how quickly it emits data to what the consumer can process. If files are read faster than they can be processed, the queue can keep growing. Making the producer wait when the queue is full prevents that backlog from growing without bound.
This example uses an asynchronous queue within one process. When asyncio.Queue(maxsize=2) is full, await put() suspends that producer coroutine until an item is removed. The event loop can run other tasks in the meantime. Python Queue documentation

The important step is that produce waits for each put to finish. Creating an unlimited number of separate Tasks for put lets waiting work accumulate outside the bounded queue.
A producer waiting at a full queue
import asyncio
async def produce(queue):
peak = 0
for item in range(6):
await queue.put(item)
peak = max(peak, queue.qsize())
await queue.put(None)
return peak
async def consume(queue):
values = []
while True:
item = await queue.get()
try:
if item is None:
return values
await asyncio.sleep(0.01)
values.append(item)
finally:
queue.task_done()
async def main():
queue = asyncio.Queue(maxsize=2)
async with asyncio.TaskGroup() as group:
producer = group.create_task(produce(queue))
consumer = group.create_task(consume(queue))
await producer
await queue.join()
assert consumer.result() == list(range(6))
assert producer.result() <= 2
print(consumer.result())
if __name__ == "__main__":
asyncio.run(main())Run this on Python 3.11 or later. The producer sends the six values 0 through 5; None is reserved as the end marker and is not an input value. For every item retrieved with get, including the marker, the consumer calls task_done. After the producer has enqueued the final marker, join confirms that all items have been accounted for, and leaving TaskGroup also waits for the tasks to finish.
If the consumer fails with an ordinary exception other than CancelledError, TaskGroup cancels the producer too, so it does not remain waiting indefinitely at a full queue. Cancelling only the consumer task does not trigger this failure-propagation rule, and the producer may keep waiting. To stop both tasks when a request is abandoned, connect termination to their owning scope, for example by cancelling the parent task. TaskGroup exception and cancellation rules
task_done balances the queue's unfinished-item accounting; it does not certify that the business operation succeeded. A processing failure propagates through the task's exception.
Non-blocking flow control in Reactive Streams

The opening sentence of the official Reactive Streams introduction, captured on October 28, 2026. non-blocking back pressure relates to keeping an asynchronous stream flowing without pushing an unbounded buffering burden onto the receiver. Original text, Official specification and MIT-0 license.
Reactive Streams defines Publisher, Subscriber, and Subscription interfaces that signal consumer demand. The Queue example shows the same flow problem through a bounded buffer and waiting; it implements neither those interfaces nor the specification's conformance tests. Publisher rule 1.1 in the specification
Which quantity is being limited?
Mechanism | What it directly controls | Example |
|---|---|---|
Rate limiter | Requests permitted over a time interval | Requests accepted per second |
Bulkhead or concurrency limit | Tasks using resources at the same time | Slots for external API calls |
Backpressure | Flow between producer and consumer | Waiting to produce more when the buffer is full |
- Mechanism
Rate limiter
- What it directly controls
Requests permitted over a time interval
- Example
Requests accepted per second
- Mechanism
Bulkhead or concurrency limit
- What it directly controls
Tasks using resources at the same time
- Example
Slots for external API calls
- Mechanism
Backpressure
- What it directly controls
Flow between producer and consumer
- Example
Waiting to produce more when the buffer is full
These mechanisms can be combined. Even with a queue capacity of 2, an item already taken by the consumer and an item the producer is about to enqueue exist separately. Items can also have different sizes, so distinguish the item-count limit imposed by maxsize=2 from a byte limit on the process's total memory.
If the input source cannot be paused, choose a policy such as dropping items, keeping only the latest value, storing data on disk, or rejecting admission. Adding a queue limit while reporting discarded items as successful changes the business contract. This example waits and processes every input value in order.