# Delivery groups

Give each tenant, account or other group its own delivery rate, so one burst doesn't starve everyone else.

A destination has one queue. If one of your tenants triggers a flood, everyone behind it waits. Delivery groups split that queue by a value in each request, and give every group its own rate and its own concurrency.

## Configure it

Set `groups` on a URL destination:

```json
{
  "groups": {
    "key": "body.customer_id",
    "rate": 5,
    "period": "second",
    "max_in_flight": 2,
    "overrides": {
      "cus_priority": { "rate": 50, "period": "second" }
    }
  }
}
```

| Field | Meaning |
|---|---|
| `key` | One path into the request **as received**: `body.<path>`, `headers.<name>` or `query.<name>`. |
| `rate`, `period` | The default cap for every group: 1 to 1,000 per `second`, `minute` or `hour`. |
| `max_in_flight` | Optional. Requests out at once per group, 1 to 50. |
| `overrides` | Up to 100 group values with their own rate, period and `max_in_flight`. |

## How it behaves

- Each group has its own rate. Busy groups take turns, and idle groups hold nothing back.
- The destination's own `max_in_flight` and `rate_per_second` remain the **ceiling** over all groups.
- An event with no value at the key goes into the `unknown` group, which has the default rate.
- The group is worked out **once**, when the event reaches the destination. Changing the rule affects new events; a redrive works it out again.

## See what is happening

`GET /v1/destinations/:id/groups` lists the groups seen on a destination. In **Events** you can filter by `delivery_group`. If a group's oldest unsent event has waited 15 minutes, Ensue sends a `destination.group_backlog` [notification](/gateway/notifications/), and `destination.group_backlog_cleared` once they catch up.

> [!NOTE]
> Groups are for fairness between senders, not for protecting a downstream API. For that, set a single rate on the destination with the [delivery policy](/gateway/delivery-policy/).