Async work
Async work moves a slow task out of the request path, so the caller gets an answer before the task ends. A call to an email provider takes 150 ms, but a queue accepts the job in 0.5 ms. A worker then does the slow part at its own pace.
See it on the board
The same traffic runs on two boards. The simulator measured both when this page was built.
| Measure | Goal | Signup waits for the email provider | Durable queue between signup and email |
|---|---|---|---|
| p99 latency | under 150 ms | 632 ms Fail | 70 ms Pass |
| Lost writes | none | 0 Pass | 0 Pass |
| Completion time | under 25 s | 0 s Pass | 20.3 s Pass |
| Monthly cost | 12 USD/mo | 16 USD/mo | |
| Error rate | 0% | 0% | |
| Level rules | none broken | Board is not complete Fail | Pass |
Key numbers
| Number | Value |
|---|---|
| Call to the email provider, median | 150 ms |
| Call to the email provider, p99 | 300 ms |
| Write one job to the queue, median | 0.5 ms |
| Jobs per second, one queue | 20,000 ops/s |
| Price of one queue | 4 USD/mo |
4 workers · 3 jobs waiting · wait 33 ms
How it works
Some work does not need to end before the user gets an answer. A welcome email, a thumbnail or a report can run a few seconds later. If the request waits for that work, the user waits too, and each slow call holds a server worker.
With async work, the service writes a job to a queue and answers at once. A worker reads the job and does the slow part. The request path now contains only the queue write, which is fast and steady. The worker runs at its own pace, retries a failed call and takes up a burst over time.
The queue must keep each job safe. If it keeps jobs only in memory and restarts, those jobs are lost, but the user already got a success answer. A durable queue writes each job to disk before it confirms. The user also needs a way to see the result later, such as a status page or a notification.
Async work is harder to follow. A job can wait in the queue for a long time, run twice after a retry, or fail when nobody watches. Measure the time from accept to finish, not only the request time.
In the levels you move slow work behind a queue and keep each job safe until a worker completes it.