GuideAdvanced
Python Async And Concurrency
Concurrency doesn't make work faster: it eliminates the time your program spent not working. That distinction between waiting (network, disk, an external service) and computing (processor at 100%) is what this whole guide hinges on, and it's the thing almost nobody has straight before starting. You work through a single realistic case — Faro, a service that watches the price of 300 products across 12 online stores and today takes 40 minutes because it does everything sequentially — and take it, module by module, to a concurrent collector running in about 2 minutes. You'll learn the real mental model behind `async`/`await` (why `async def` on its own doesn't speed up anything), how to launch and control hundreds of tasks with courtesy limits so you don't overwhelm the other side, how to handle partial failures and cancellation, when to use threads for blocking code that's someone else's and can't be rewritten (a third-party library, say), and when to use processes for pure computation that no amount of `async` or threading will speed up because of the GIL. The guide closes with the problems that only show up in production under real volume and time — memory, connections, graceful shutdown, debugging intermittent bugs — and with a final project where you defend, with numbers, which tool you used for each layer and what you deliberately left sequential.
- 64
- lessons
- 8
- modules
- English · Spanish
- available in
- Yes
- certificate
- Free
- access
Outcomes
What you'll be able to do
- Precisely distinguish waiting work from computing work, measuring with `time.perf_counter()` and `time.process_time()` instead of guessing
- Understand what a coroutine really is, what `await` does, and why `async def` doesn't speed anything up on its own — only when there's something else to overlap it with
- Launch and coordinate hundreds of concurrent tasks with `asyncio.TaskGroup`, `asyncio.Semaphore` to cap load per resource, and timeouts with `asyncio.timeout`
- Handle partial failures, exceptions inside tasks, and cooperative cancellation, deciding with judgment when to abort everything and when to keep what already worked
- Use threads (`asyncio.to_thread`) to integrate blocking third-party code that can't be rewritten, without freezing the event loop
- Recognize and avoid race conditions in data shared between threads
- Use processes (`ProcessPoolExecutor`) to parallelize real computation, first calculating the cost of process startup and inter-process data transfer
- Recognize the problems that only appear with volume and time in production: memory leaks, connection exhaustion, shutdowns that leave work half-done, bugs that only happen once in a hundred runs
- Choose with judgment between `async`, threads, and processes based on the real nature of the work, instead of applying concurrency by reflex
- Measure a concurrent system's improvement honestly and defend in writing which parts were left sequential and why
Before you start
What you need to bring
It's for you if...
- Intermediate-level Python developers who already used `async`/`await` because a framework (FastAPI, say) told them to, but never understood why it works
- Devs with a slow script or service from making many network calls one after another, who suspect concurrency would help but don't know where to start
- Teams that need to integrate a third-party library that blocks and has no async version, without freezing the rest of their application
- People preparing technical interviews where they're asked about the GIL, the difference between concurrency and parallelism, or when to use threads versus processes
- Anyone who's written `asyncio` code that "works" but was never measured, and wants to know if it's actually gaining anything
Requirements and materials
- Know Python: functions, classes, exceptions, and having written programs that call an API or read files
- No prior experience with asynchrony, threads, or processes is required
- It helps to have felt the problem this guide solves: a script that takes minutes making requests one at a time while the computer does nothing
- No need to know FastAPI or any framework: the guide explains why frameworks require `async def` without teaching the framework itself
Content
The syllabus, module by module
Open any of them to see its lessons.
- 1. Module introduction: what a coroutine really is
- 2. `async def` doesn't make anything fast by itself
- 3. `await`: yielding the turn, not sitting and waiting
- 4. The event loop as a turn manager
- 5. The coroutine nobody awaited
- 6. Your first truly async program
- 7. Why a blocking `sleep` ruins everything
- 8. Project: convert a sequential script
- 1. Module introduction: from one at a time to all together
- 2. Tasks: starting something without waiting for it
- 3. Waiting for a group of tasks
- 4. Task groups and why they're the recommended way
- 5. Limiting how many run at once
- 6. Results that arrive out of order
- 7. Timeouts and what to do when they expire
- 8. Project: 300 requests in the time of one
- 1. Module introduction: errors change shape
- 2. Exceptions inside concurrent tasks
- 3. One failure among three hundred: continue or abort
- 4. Cancellation: how a task is stopped
- 5. Cleaning up on exit even when cancelled
- 6. Retrying without hammering the other side
- 7. Bugs that only appear concurrently
- 8. Project: make your collector robust
- 1. Module Introduction: When Async Isn't Enough
- 2. What a Thread Is and What It Shares
- 3. Blocking Code You Can't Rewrite
- 4. Moving Blocking Work Off the Event Loop
- 5. Shared Data and the Race Condition
- 6. Locks and Why You Use Them Sparingly
- 7. When Threads Beat Async
- 8. Project: Integrate a Blocking Library
- 1. Module Introduction: The Work That Truly Burns CPU
- 2. Why Threads Don't Help With Computation
- 3. Processes: Separate Memory, Startup Cost
- 4. Distributing Work Across Processes
- 5. Passing Data Between Processes and What It Costs
- 6. When Parallelizing Isn't Worth It
- 7. Mixing Async With Processes
- 8. Project: Speed Up the Report Computation
- 1. Module Introduction: What Changes When It Runs for Real
- 2. Being a Good Citizen With Someone Else's System
- 3. Connections: Open, Reuse, and Close Well
- 4. Memory Pressure With Thousands of Tasks
- 5. Debugging Concurrent Code
- 6. Logging When Everything Happens at Once
- 7. Shutting Down Cleanly
- 8. Project: Get Faro Production-Ready
- 1. Module Introduction: Bringing the Three Tools Together
- 2. Designing the Flow Before Writing It
- 3. The Waiting Layer: Concurrent Requests
- 4. The Computing Layer: The Report in Processes
- 5. The Blocking Layer: The Library That Won't Yield
- 6. Measuring the Improvement Honestly
- 7. What You Did NOT Make Concurrent, and Why
- 8. Final Project: Faro From 40 Minutes to 2
Common questions
What people usually ask
No limit. It's a free guide: come in whenever you like, as often as you like.
No. Modules run from easier to harder, but you can jump to the one you need. Progress is saved per lesson.
Whatever is needed is listed under “What you need to bring”, above. If nothing is listed there, you can start from zero.
In the Club's WhatsApp group, and every two weeks there's a live with an instructor where questions get worked through.
Yes. It's issued automatically once you finish every lesson, with a verifiable code you can share on LinkedIn.
Start whenever you like
What students say
These reviews are from enrolled students who completed at least 50% of the course. We moderate reviews only on content grounds (spam, offensive language, personal data), never for being critical or negative.
No approved reviews yet.
Be the first to share your experience!