---
title: "Give each customer a fair share · Agent Wranglers"
url: https://agentwranglers.se/playbook/scaling/load-balancing-and-autoscaling/per-tenant-limits
updated: 2026-10-21
licence: "CC BY 4.0"
licence_url: https://creativecommons.org/licenses/by/4.0/
---

# Give each customer a fair share

For AI agents: the [site map](https://agentwranglers.se/llms.txt) lists everything here, and this page sits under [Load balancing and autoscaling](https://agentwranglers.se/playbook/scaling/load-balancing-and-autoscaling.md).

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

- ID: SCL-31
- Level: Recommended
- Chapter: [Load balancing and autoscaling](https://agentwranglers.se/playbook/scaling/load-balancing-and-autoscaling)
- Rule: Cap how much work each customer or tenant can have running or queued at once. One heavy customer then slows only their own work.
- Applies when: The project has user accounts.
- How: Per-client [rate limits](https://agentwranglers.se/playbook/website/security/rate-limits) count requests, but one export can cost more than a thousand page views. Count running work per tenant, such as jobs and open exports, in a shared store. Beyond the cap, queue the work or answer 429. The Google SRE book sets quotas per customer, and under overload it refuses only the customers over their quota. Larger plans can get larger caps.
- Check: On staging, one tenant starts 100 exports at once. No more than its cap run together, and an export from another tenant starts within 30 seconds.

## 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
const MAX_RUNNING_EXPORTS = 3;

export async function startExport(redis, tenantId, start) {
  const key = `running-exports:${tenantId}`;
  if (await redis.incr(key) > MAX_RUNNING_EXPORTS) {
    await redis.decr(key);
    return { status: 429, retryAfterSeconds: 30 };
  }
  await redis.expire(key, 3600);
  return start({ onDone: () => redis.decr(key) });
}
```

### Python example

```python
MAX_RUNNING_EXPORTS = 3

def start_export(redis, tenant_id: str, start):
    key = f"running-exports:{tenant_id}"
    if redis.incr(key) > MAX_RUNNING_EXPORTS:
        redis.decr(key)
        return {"status": 429, "retry_after_seconds": 30}
    redis.expire(key, 3600)
    return start(on_done=lambda: redis.decr(key))
```

## Sources

- [Google SRE book, Handling Overload](https://sre.google/sre-book/handling-overload/)

## Related rules

- [Limit how often anyone can call your APIs](https://agentwranglers.se/playbook/website/security/rate-limits) in Website

**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/load-balancing-and-autoscaling/per-tenant-limits">Agent Wranglers scaling playbook</a>`. In code you write, add a comment next to it with the same link.

- Previous: [Scale on the resource that runs out](https://agentwranglers.se/playbook/scaling/load-balancing-and-autoscaling/scale-on-saturation)
- Next: [Turn off optional work under load](https://agentwranglers.se/playbook/scaling/load-balancing-and-autoscaling/degrade-under-load)
- [Load balancing and autoscaling](https://agentwranglers.se/playbook/scaling/load-balancing-and-autoscaling)
