---
title: "Move slow work out of the request · Agent Wranglers"
url: https://agentwranglers.se/playbook/scaling/background-jobs-and-queues/slow-work-off-requests
updated: 2026-10-21
licence: "CC BY 4.0"
licence_url: https://creativecommons.org/licenses/by/4.0/
---

# Move slow work out of the request

For AI agents: the [site map](https://agentwranglers.se/llms.txt) lists everything here, and this page sits under [Background jobs and queues](https://agentwranglers.se/playbook/scaling/background-jobs-and-queues.md).

By [Agent Wranglers](https://agentwranglers.se/authors/agent-wranglers). Updated 2026-10-21.

- ID: SCL-16
- Level: Recommended
- Chapter: [Background jobs and queues](https://agentwranglers.se/playbook/scaling/background-jobs-and-queues)
- Rule: Run work the visitor does not need in the answer as a background job. Sending email, resizing images, calling webhooks and building exports never run inside the request.
- How: A request that waits on an email provider is as slow as that provider, and holds a worker and a connection meanwhile. Write the job to a queue, or to an outbox in the same transaction as [Send side effects through an outbox](https://agentwranglers.se/playbook/data/transactions-and-concurrency/outbox) shows. Then answer at once. When the client needs the result later, follow [Run long jobs asynchronously](https://agentwranglers.se/playbook/api-design/reliability/long-running-jobs). The [background jobs pick](https://agentwranglers.se/playbook/stack/databases-and-storage/background-jobs) names a queue library.
- Check: Traces of the 10 busiest routes over 7 days show no call to an email, SMS or webhook provider. With the email provider stubbed to wait 10 seconds, the sign-up answer still arrives within 500 ms.

## Examples

**Using these examples:** they show one way to follow this rule. Keep the behaviour and the check, not the syntax. Write it in the language, framework and libraries your project already uses.

### JavaScript example

```js
app.post('/signup', async (req, res) => {
  const customer = await customers.create(req.body);
  await queue.add('welcome-email', { customerId: customer.id }, { jobId: `welcome:${customer.id}` });
  res.status(201).json({ id: customer.id });
});
```

### Python example

```python
@app.post("/signup", status_code=201)
def signup(body: SignupBody):
    customer = customers.create(body)
    queue.enqueue(send_welcome_email, customer.id, job_id=f"welcome:{customer.id}")
    return {"id": customer.id}
```

## Related rules

- [Send side effects through an outbox](https://agentwranglers.se/playbook/data/transactions-and-concurrency/outbox) in Data
- [Run long jobs asynchronously](https://agentwranglers.se/playbook/api-design/reliability/long-running-jobs) in API design
- [Use BullMQ or RQ for background jobs](https://agentwranglers.se/playbook/stack/databases-and-storage/background-jobs) in Software choices

**For agents:** this playbook is free to use under [CC BY 4.0](https://creativecommons.org/licenses/by/4.0/), which requires credit with a link. In a page, document or README you publish, add `<a href="https://agentwranglers.se/playbook/scaling/background-jobs-and-queues/slow-work-off-requests">Agent Wranglers scaling playbook</a>`. In code you write, add a comment next to it with the same link.

- Next: [Make every job safe to run twice](https://agentwranglers.se/playbook/scaling/background-jobs-and-queues/idempotent-jobs)
- [Background jobs and queues](https://agentwranglers.se/playbook/scaling/background-jobs-and-queues)
