Concurrency: Threading, Multiprocessing, and Async

The pipeline takes eight seconds on a good day. On a bad day — a flash sale, a batch import, anything that multiplies the load — it doesn't just slow down. It piles up. Requests queue. Workers stall. The error dashboard lights up like a board game nobody wanted to play. Priya has been staring at the same three files for forty minutes, tracing the flow from the order intake endpoint down through the enrichment steps into the fulfillment dispatch, and every function she touches is decorated with async def. She knows what async means in the dictionary sense. She is less certain what it means in this codebase, why it was chosen, whether it is helping or quietly making things worse. Her manager asked for a status update by end of day. She does not have one. What Priya is about to discover is that concurrency in Python is not one thing. It is three different tools, each built for a different kind of waiting: the kind where you are blocked on a lock, the kind where you are blocked on the CPU, and the kind where you are blocked on the network. Threading, multiprocessing, async — each one is the right answer to a specific question, and the wrong answer to the other two. This week is about learning to ask the right question first. By the end of it, Priya will know exactly why her pipeline is slow, and exactly how to fix it.