Async/await maps coroutines onto event loops. The basic example is easy; production patterns (cancellation, concurrent operations, error handling, backpressure) are where teams get tangled. The good patterns are language-agnostic.
Concurrent independent operations
await Promise.all([fetchA(), fetchB(), fetchC()]) in JS, asyncio.gather in Python, structured concurrency in Kotlin. Sequence requests in parallel when their inputs are independent. Easy 3x speedup; commonly missed.
Cancellation
Long async operations need to be cancellable: timeout, user cancels, parent cancels. Use AbortSignal (JS), CancellationToken (.NET), structured concurrency scopes (Kotlin, Java). Don't ignore cancellation — leaks zombie operations.
Error handling
Errors in async operations propagate through await. Uncaught rejected promises crash the process (in modern Node). Test the error paths; they're harder to reproduce than sync errors.