---
title: "Give every request a time limit · Agent Wranglers"
url: https://agentwranglers.se/playbook/app-ui/resilience/request-timeouts
id: APP-51
level: Required
risk: outage
updated: 2026-10-22
build: a2a6bdfed830
tokens: 996
licence: "CC BY 4.0"
licence_url: https://creativecommons.org/licenses/by/4.0/
---

# Give every request a time limit

For AI agents: the [site map](https://agentwranglers.se/llms.txt) lists everything here, and this page sits under [Resilience](https://agentwranglers.se/playbook/app-ui/resilience.md).

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

- ID: APP-51
- Level: Required
- Chapter: [Resilience](https://agentwranglers.se/playbook/app-ui/resilience.md)
- Rule: Give every request from the screen a time limit, say when a request is slow, and retry only reads and requests with an idempotency key.
- Check: A browser test holds the orders request open and never answers it. "Still working" appears after 3 seconds, and the error view with a retry button appears at the time limit. A second test holds a write without an idempotency key open, and it is sent once only.
- Risk: The app down or unusable
- How: Abort reads after 10 to 15 seconds and writes after 30, with `AbortSignal.timeout`. Keep these longer than the server's own limits, as [timeouts](https://agentwranglers.se/playbook/api-design/reliability/timeouts.md) says. After 3 seconds, show "Still working" in the view. Retry reads with [backoff and jitter](https://agentwranglers.se/playbook/api-design/reliability/retry-backoff.md), at most 3 times. Honour `Retry-After`. Never repeat a write without an [idempotency key](https://agentwranglers.se/playbook/api-design/reliability/idempotency-keys.md). Cancel requests whose answer is no longer needed, such as an old search.

## 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.

### TypeScript example

```ts
const READ_TIMEOUT_MS = 12_000;
const SLOW_AFTER_MS = 3_000;

export async function loadWithTimeLimit<T>(url: string, onSlow: () => void, cancel?: AbortSignal): Promise<T> {
  const slowTimer = setTimeout(onSlow, SLOW_AFTER_MS);
  const signals = [AbortSignal.timeout(READ_TIMEOUT_MS), ...(cancel ? [cancel] : [])];
  try {
    const response = await fetch(url, { signal: AbortSignal.any(signals) });
    if (!response.ok) throw new LoadError(response.status, await response.json().catch(() => null));
    return response.json();
  } finally {
    clearTimeout(slowTimer);
  }
}
```

### Python example

```python
from playwright.sync_api import expect

def test_slow_orders_show_progress_then_error(page):
    held_open = []
    page.route("**/api/orders*", held_open.append)
    page.goto("https://staging.example.com/orders")
    expect(page.get_by_text("Still working")).to_be_visible(timeout=4_000)
    expect(page.get_by_role("button", name="Try again")).to_be_visible(timeout=15_000)
```

## Sources

- [DOM Standard on AbortSignal.timeout()](https://dom.spec.whatwg.org/#dom-abortsignal-timeout)

## Related rules

- API-34 [Retry with backoff and jitter](https://agentwranglers.se/playbook/api-design/reliability/retry-backoff.md) in API design
- API-35 [Set timeouts on every call](https://agentwranglers.se/playbook/api-design/reliability/timeouts.md) in API design
- API-32 [Accept idempotency keys on POST that creates or charges](https://agentwranglers.se/playbook/api-design/reliability/idempotency-keys.md) in API design

**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/app-ui/resilience/request-timeouts">Agent Wranglers web app interface playbook</a>`. In code you write, add a comment next to it with the same link.

- Previous: [Contain each crash to its panel](https://agentwranglers.se/playbook/app-ui/resilience/error-boundaries.md)
- Next: [Say when the network is gone](https://agentwranglers.se/playbook/app-ui/resilience/offline-behaviour.md)
- [Resilience](https://agentwranglers.se/playbook/app-ui/resilience.md)
