Module 7 · Lesson 1 of 5
Not everything belongs in the request
What the user must wait for, and what can happen later.
It's fest night. Gatepass's booking endpoint reserves the seat, charges the card, renders a PDF ticket, emails it and sends an SMS, all before it replies. Then the SMS provider slows down to four seconds per message. Nothing in Gatepass is broken, yet bookings start timing out, fans tap “Pay” again, and support gets angry messages about double charges.
A request is a promise to wait
Whatever you do inside a request handler, the user waits for all of it. Their phone shows a spinner. Your server holds a connection, a worker thread or event-loop slot, and maybe a database connection, for the whole duration. If the handler calls five things in a row, the user's wait is the sum of all five, and the booking's reliability is the product of theirs.
Look at the reliability side. If the payment provider, the PDF renderer, the email API and the SMS API are each up 99.5% of the time, the chance all four work for a given booking is 0.995⁴, about 98%. One booking in fifty fails because of something the fan didn't need yet.
What the user must wait for
Sort every step with one question: does the response depend on it?
- Reserving the seat decides the answer (“you got C14” or “sorry, it's gone”). It must run in the request.
- Charging the card too. The fan has to know whether they paid.
- The PDF, the email and the SMS don't change the answer. The booking is real the moment the transaction commits. Delivering the ticket can happen a few seconds later.
That gives you the split: do the decision in the request, record that the follow-up work is owed, reply, and do the follow-up work afterwards in the background.
Do in the request only what the answer depends on. Everything else is a promise you keep after replying.
Try it: when the SMS provider slows down
Start with everything inline and drag the SMS response time to 4 seconds. Then move the PDF, email and SMS out of the request.
Try it
What is the fan actually waiting for?
Slow the SMS provider down, then move steps out of the request. The dashed line is the app's 5-second timeout.
Run after the response (in a queue)
Everything in the request
1.6 s
Your split
1.6 s
All in request
1.6 s
user waits
Your split
1.6 s
user waits
If SMS is down
Booking fails
an SMS outage = a booking outage
Two things change when you move work out. The obvious one is speed: the fan's wait drops from seconds to under a second, and it no longer depends on the SMS provider at all. The less obvious one is failure isolation: an SMS outage now delays texts instead of stopping ticket sales. The reserve and payment steps can't move, and that's fine. They're the product.
The new contract with the user
Asynchronous work changes what your response means. “201 Created” no longer says “you have your ticket in your inbox”. It says “your booking is confirmed and the ticket is on its way”. Design the product around that:
- The confirmation screen shows the ticket from the database immediately, with a QR code the app can render itself. The PDF is a convenience, not the ticket.
- The “My tickets” page shows delivery status: “Email sent”, “SMS pending”.
- If delivery fails for good, someone (or something) notices. That's the dead-letter lesson at the end of this module.
How work gets “later”
The tempting shortcut is to start the work without waiting for it: fire off a promise or a thread inside the request handler and reply right away. It looks async and it is fragile. If the server restarts during a deploy or crashes, every in-flight email is gone, and nothing records that it was ever owed.
Background work needs to be written down somewhere durable before you reply, so another process can pick it up even if this one dies. That's a queue, and the processes that take work from it are workers. The next lesson builds them.
Check yourself
Which of these should stay inside Gatepass's booking request?
Key takeaways
- Everything inside a request adds to the user's wait, and every dependency in it can fail the whole request.
- Keep in the request only what the response depends on. For a booking: the seat and the payment.
- Moving slow work out makes responses fast and stops a slow third party from taking your main feature down.
- Async work must be written down durably before you reply. A background thread in the web server is not durable.
- Asynchronous work changes the promise your response makes, so the product must show pending and failed states.
Finished reading?
Mark it complete to tick it off in the course.