Async Await Under The Hood
Async await reads like sequential code but the compiler rewrites it into a state machine. Each await point becomes a place where the function can pause and later resume exactly where it left off.
When you call an async function, it runs until it hits an await on something not yet ready. At that point the function captures its local variables and the position of the await into a saved state, then returns control to the scheduler. It is suspended, not blocked, so the underlying thread is free to run other work.
When the awaited value becomes ready, the scheduler resumes the state machine. It restores the locals and jumps back to the saved position, continuing as if no pause happened.
- No thread is blocked while awaiting, which is why one thread can drive thousands of awaiting tasks.
- Locals survive the pause because they are stored in the state machine, not on a parked stack.
- Cooperative A task only yields at await points, never in the middle of plain code.
This is why async is cheap. A suspended task is just a small heap object holding its state, far lighter than an idle operating system thread.
Key idea
Await compiles a function into a state machine that saves its locals and position, suspending without blocking a thread until the awaited value is ready.