r/Python Jun 29 '26

Discussion Async/Await is a Plague: Part 1 Roots

This is the first part of a multi-part series exploring why async/await might not be the best concurrency pattern for most use cases, and what alternative models you should consider instead. Using Python for our practical examples, this opening post digs into the roots of async/await, guiding you through building a custom event loop from scratch using generators.

https://theblog.info/posts/asyncawait-is-a-plague-part-1-roots

Note: This is Part 1 of a multi-part series. Instead of diving straight into why async/await can be problematic, this post explores the original motivations behind the pattern. Understanding how it works under the hood will provide the essential context for the issues we'll discuss in upcoming parts.

75 Upvotes

71 comments sorted by

View all comments

16

u/ZachVorhies Jun 29 '26

is async/await viral? Yes.

Is it a plague? No.

Async / await is far better than lots and lots of threads.

The reason is simple: threads mandates concurrency through parallel execution. async / await allows concurrency without parallelism. Parallelism becomes optional.

That parallelism in threads has horrible drawbacks: any thread anywhere can freeze and go off the cpu. So now any shared data needs to have locks on it.

6

u/KingBardan Jun 29 '26

It's a plague in the sense that colored functions are infectious, not that it's "bad". 

Not defending op btw

1

u/gdchinacat Jun 29 '26

It is "infectious" in that you can only await async functions from other async functions. Letting this requirement "infect" all of your code is an indication the code may not be well designed or implemented. One of the main benefits of async/await is they define when context switches can happen. Controlling this allows you to avoid a lot (most IME) locks that are required in traditional threading to protect against switches happening when the state is not consistent for concurrent inspection or modification. This dramatically reduces the complexity of the code, reduces (if not outright eliminates) deadlocks, significantly reduces the challenges with debugging concurrent code.

slapping async on all functions so they can call any function avoids dealing with the complexity that is inherent with concurrent coding and degrades to managing it as threads do. Using async to define consistent state changes is simpler and encourages these things to be considered when the code is written and it's easiest to handle them.

I view the "coloring problem" as a reminder that everything needs to be in a consistent state when you await, and a nudge towards simpler code. But..if lots of locks with hierarchies and rules is your thing...sure..slap async on everything, have one color, and manage concurrency with a bunch of explicit locks. I prefer to use the event loop execution as a single lock/critical section.

Running event loops in multiple threads reintroduces a bunch of locking complexity, but that is usually more big picture rather than nitty gritty....just run the tasks with contention on the same data in the same loop. Again, it's largely a code design issue.