async/await is syntax that lets a function pause on a promise and resume later without callbacks. Under the hood it is promise.then plus a suspended stack frame, scheduled through the microtask queue.
An async function is a normal function with two guarantees: it always returns a promise, and it can use await inside its body. Callers get a promise immediately, even if the body has not finished, and the eventual return value or thrown error becomes that promise's fulfillment value or rejection reason.
await takes any value, converts it to a promise, and suspends the function until that promise settles. The engine saves the current stack frame, registers the rest of the function as the promise's reaction, and returns control to whoever called the async function. When the promise settles, the reaction runs as a microtask and the frame is restored with the awaited value in place of the await expression.
The mechanism is the same one generators use. A generator pauses on yield and resumes on next(); an async function pauses on await and is resumed by a promise reaction. Early transpilers literally compiled async/await into a generator driven by a promise loop, and V8's implementation still shares the suspend and resume machinery.
Because resumption happens through microtasks, async code interleaves with other work at predictable points. Everything before the first await runs synchronously on the caller's stack. Everything after runs later, after the current synchronous code finishes and before any timer or I/O callback, because the event loop drains the microtask queue between tasks.
Interview framing: define Async/Await in one sentence, then explain one concrete runtime behavior and one common pitfall with a short code example.