Photo by Dominic Kurniawan Suryaputra / Unsplash

TIL - asyncio.Queue Is the Backbone of Async Producer-Consumer Pipelines

Today I Learned May 1, 2026

asyncio.Queue is a coroutine-safe FIFO that decouples producers from consumers inside a single event loop — no threads, no locks, no race conditions.

import asyncio

async def producer(queue: asyncio.Queue, items: list):
    for item in items:
        await asyncio.sleep(0.05)   # simulate I/O
        await queue.put(item)
        print(f"Produced: {item}")
    await queue.put(None)           # sentinel to signal done

async def consumer(queue: asyncio.Queue):
    while True:
        item = await queue.get()
        if item is None:
            break
        print(f"Consumed: {item}")
        queue.task_done()

async def main():
    q = asyncio.Queue(maxsize=3)    # back-pressure: blocks producer if full
    await asyncio.gather(
        producer(q, list(range(6))),
        consumer(q),
    )

asyncio.run(main())

maxsize=N applies natural back-pressure — the producer awaits when the queue is full, preventing unbounded memory growth. queue.join() blocks until all task_done() calls have been made, useful for batch processing.

Tags