# Quota tiers

Define rate limits once, name the plan and assign it to as many API clients as needed.

A quota tier is a named, reusable set of [rate limiting](https://zato.io/docs/admin/guide/rate-limit.html) rules. Instead of configuring the same limits on each security definition one by one, you define the limits once, give them a name - Bronze, Silver, Gold - and assign that name to as many API clients as needed.

A tier is stored once and referenced by name, so the same limits govern any number of consumers:

- Define a plan once and apply it to hundreds of API clients
- Change the plan in one place and every client that references it is subject to the new limits immediately
- Assign a tier to a whole [security group](https://zato.io/docs/admin/security/channel.html) so every member follows the same plan

Counting stays per consumer - clients on the same tier never share counters - and clients see their allowance through the `X-RateLimit-Limit` and `X-RateLimit-Remaining` response headers.

## Tiers vs. direct rate limiting {#tiers-vs-direct-rate-limiting}

A tier holds the same rules that the rate limiting editor produces - address lists, time ranges, rate, burst, limit and time unit. The difference is reuse:

- **Direct rules** belong to one security definition or one channel and are edited there
- **A tier** is a standalone object that definitions and groups reference by name

A security definition either references a tier or has its own rules - never both.

REST and SOAP channels follow the same rule - a channel either references a tier or has its own rules, never both. Both levels still stack - a request must pass the security definition's tier or rules first and the channel's tier or rules next.

## Define a tier {#define-a-tier}

In Dashboard, navigate to `Security -> Quota tiers` and click **Create a quota tier**.

The editor is the same rule builder as for rate limiting - one or more rules, each with an address list and time ranges holding rate, burst, limit and time unit. Give the tier a name and, optionally, a description, then save.

The tier list shows each tier's limits along with how many definitions and groups reference it. You cannot delete a tier that is still referenced.

## Assign a tier to a security definition or a channel {#assign-a-tier-to-a-security-definition-or-a-channel}

Open the **Rate limiting** link of a [Basic Auth](https://zato.io/docs/security/basic-auth.html) or [API key](https://zato.io/docs/security/api-keys.html) definition, or of a REST or SOAP channel. At the top of the page there are two tabs:

- **Quota tier** - pick a tier from the select and the definition or channel follows the tier's rules - the page hides the rule builder
- **Custom rules** - the page shows the rule builder and the definition or channel has its own rules

If no tiers have been defined yet, the Quota tier tab offers a **Create one** button that opens the tier editor.

Counters are always tracked per security definition. Two definitions on the same Gold tier each get the full Gold allowance - each keeps its own counters.

## Assign a tier to a security group {#assign-a-tier-to-a-security-group}

A tier set on a [security group](https://zato.io/docs/admin/security/channel.html) applies to every member of that group, again with per-member counting. In the group's create or edit dialog, pick the tier from the **Quota tier** select.

Precedence, from strongest to weakest:

1. A definition's own custom rules
2. A tier assigned directly to the definition
3. A tier assigned to a group that the definition belongs to

Group membership changes take effect immediately - adding a member to a group with a tier puts that member on the tier's plan, unless it has its own rules or its own tier.

## Response headers {#response-headers}

Requests governed by a security definition's limits - whether from a tier or from custom rules - receive two response headers:

```bash
$ curl -v http://user:password@localhost:11223/api/customer

< HTTP/1.1 200 OK
< X-RateLimit-Limit: 1000
< X-RateLimit-Remaining: 993
```

- `X-RateLimit-Limit` - the total allowance of the most constrained matching limit
- `X-RateLimit-Remaining` - how much of that allowance is left

When the limit is exhausted, the headers accompany the 429 response next to the existing `Retry-After`:

```bash
$ curl -v http://user:password@localhost:11223/api/customer

< HTTP/1.1 429 Too Many Requests
< Retry-After: Mon, 01 Jun 2026 00:00:00 GMT
< X-RateLimit-Limit: 1000
< X-RateLimit-Remaining: 0
```

Channel-level limits add no headers - the headers describe the consumer's allowance only.

## Enmasse {#enmasse}

You define and assign tiers in [enmasse](https://zato.io/docs/admin/enmasse.html) YAML too. The top-level `quota_tier` list defines the tiers, and `security` and `groups` entries reference them by name through a `quota_tier` key:

```yaml
quota_tier:
  - name: Gold
    description: Premium partners
    rules:
      - cidr_list:
          - 0.0.0.0/0
        time_range:
          - is_all_day: true
            disabled: false
            disallowed: false
            rate: 100
            burst: 200
            limit: 100000
            limit_unit: month

security:
  - name: partner.credentials
    type: basic_auth
    username: partner1
    quota_tier: Gold

groups:
  - name: premium.partners
    quota_tier: Gold
    members:
      - partner.credentials
```

Enmasse rejects a security definition with both `quota_tier` and `rate_limiting` at import time - the two are mutually exclusive.

## See also {#see-also}

- [Rate limiting and firewall](https://zato.io/docs/admin/guide/rate-limit.html) - The rules that a tier holds and how they are evaluated
- [Security groups](https://zato.io/docs/dev/rest/security-groups.html) - Applying one tier to every member of a group
- [Enmasse](https://zato.io/docs/admin/enmasse.html) - Defining and assigning tiers in YAML

## Learn more {#learn-more}

- [Production checklist](https://zato.io/docs/admin/production-checklist.html) - What to confirm before an environment takes real traffic
- [Audit log](https://zato.io/docs/admin/audit-log/) - Every request, response and error, and what you can do with them afterwards
- [Health checks](https://zato.io/docs/admin/health-checks.html) - Have Zato ping your outgoing connections instead of waiting for traffic to fail
- [Logging](https://zato.io/docs/admin/logging.html) - What is written where, and how to ship it to Splunk, Loki, Elastic or Datadog
- [GitOps with enmasse](https://zato.io/docs/admin/enmasse.html) - Keep the whole environment in git as YAML and import it anywhere
