Consider const response = await fetch(url);. This trace describes the scheduling boundary, not every native networking implementation detail. The source code after await is a continuation that runs only after the awaited promise settles.
1. Execute the current JavaScript
The function runs synchronously until it reaches await. It evaluates fetch(url) and receives a promise. If the promise is still pending, the async function suspends and returns control to its caller; it does not block the JavaScript thread waiting at that line.
2. Progress the operation
The runtime initiates the operation through native bindings and platform facilities. Network progress may be handled by the operating system and runtime event mechanisms. Other work may use worker threads or a runtime worker pool; the path varies by API and platform.
3. Settle and schedule
When the operation produces a result or error, the promise is fulfilled or rejected. The async function's continuation becomes runnable according to the runtime's job-queue rules. The event loop cannot run that JavaScript while a long synchronous callback still occupies the thread.
4. Resume the function
The continuation runs later and receives the response or throws the rejection at the await point. This sequencing makes asynchronous code readable, but it does not parallelize CPU-heavy JavaScript. Move CPU-bound work to a worker or another process when parallel execution is needed, and account for message-copying and lifecycle costs.
Node.js documents the event loop and worker pool; use those runtime-specific rules rather than assuming every language schedules promises identically.