API rate limiting controls how many requests a client can make to your APIs within a given time window. In Zato, the same mechanism also works as an IP-based firewall - you can silently drop connections from unwanted addresses, exactly like a network firewall would.

A few real-world examples of how you can use it:
Cap each API partner at 1,000 requests per hour across all endpoints they authenticate to (identity-aware rate limiting), no matter how many individual REST endpoints they invoke
Apply stricter limits during maintenance windows and relax them during business hours - or the other way around, allow only a few req/s throughout the day but allow 10x more between 01:00 and 02:00 when you know batch loading processes run - with each time range tracked by its own independent counters
Set both a per-second burst limit and a per-day or per-month hard cap on the same rule, so short traffic spikes are absorbed while the total daily or monthly budget is still enforced
Allow only your internal address ranges to reach an endpoint and silently drop everything else, turning a REST channel into a private API without a separate network-level firewall
Block entire IP ranges with a silent TCP drop that reveals nothing about the server behind the address - scanners and automated tools see only a connection reset, identical to a network firewall
Rate limiting can be configured on two levels, either in combination or independently.
When both are configured, security definition limits are checked first. If the security definition allows the request through, the channel limits are checked next. This two-level design means you can set a global cap per partner (via security definitions) and a separate, tighter cap on individual endpoints (via channels), without the two interfering.

Each rate limiting configuration consists of one or more rules. Each rule has an address list - a set of IP addresses or ranges that it matches against - and one or more time ranges with their own limits. There is no hard cap on the number of addresses per rule or on the number of rules per channel.
Addresses can be single IPs (e.g. 192.168.1.10) or ranges in subnet notation (e.g. 10.0.0.0/8 meaning all addresses from 10.0.0.0 to 10.255.255.255). Both IPv4 and IPv6 are supported.
If a rule's address list is empty, it matches all client IP addresses. If addresses are specified, only requests from matching addresses are subject to that rule. Rules are evaluated top to bottom - the first rule whose address list matches the client IP is used.
You can combine allow and deny rules to build precise IP access policies. For example, a rule allowing 10.0.0.0/8 followed by a catch-all disallow rule creates a classic allowlist.
A rule disallowing 203.0.113.0/24 followed by a permissive catch-all creates a denylist. More specific addresses in earlier rules naturally take precedence over broader ranges in later rules, because rules are evaluated in the order you define.

Each rule has at least one time range - the all-day default. You can add additional time ranges for specific hours of the day (e.g. 09:00-17:00). When a request arrives, Zato checks time ranges in order:
Each time range has its own independent set of limits and counters.
Each time range gives you two controls that work together:


When a request is denied, Zato always returns HTTP 429 Too Many Requests with a Retry-After header containing an HTTP-date timestamp indicating when the client can retry.
$ curl -v http://user:password@localhost:17010/api/customer
< HTTP/1.1 429 Too Many Requests
< Retry-After: Mon, 01 Jun 2026 00:00:00 GMT
{
"result": "Error",
"cid": "20260504-113121-2314-57a1b3646a55499ea",
"details": "Too many requests"
}

If a time range is marked as disallowed, Zato does not return an HTTP error at all. Instead, it silently drops the TCP connection, exactly as a network firewall would, without any response headers, response bodies, or HTTP status codes - the connection is simply closed, and the client sees a connection reset or timeout.
This is useful for blocking entire IP ranges, denying access outside business hours, or implementing geographic restrictions at the application level of Zato.
$ curl -v http://user:password@localhost:17010/api/customer
curl: (56) Recv failure: Connection reset by peer

A time range can be disabled, which means it is skipped during evaluation. If the all-day default is disabled and no other time range matches, rate limiting is effectively turned off for that rule (meaning all traffic is always allowed). This lets you temporarily suspend rate limiting without deleting the configuration.
Disabling a rule takes effect immediately and does not reset counters. When you re-enable the rule, the existing counters resume from where they were. If you need a clean slate, use the Clear counters link separately.
All counters are reset to zero when the server restarts. Rate limiting rules and configuration are loaded automatically on startup, but, since the counters themselves are held in memory and are not permanent, they all start from zero again after a restart.
In Dashboard, navigate to the REST channel list via Connections -> Channels -> REST. Each channel row has a Rate limiting link.
Click it to open the rate limiting editor for that channel.
From here you can:
Navigate to Security -> Basic Auth or Security -> API Keys. Each definition row has a Rate limiting link, the same as for channels.
Rules configured here apply to every channel that uses this security definition. The limit follows the credential, not the endpoint. For example, if a Basic Auth user "api-partner-1" has a limit of 100 requests per minute, that limit is enforced across all channels that "api-partner-1" authenticates to - whether the partner calls /orders, /invoices, or any other endpoint protected by the same definition.
This is identity-keyed rate limiting: the counter is tracked per security definition, so a single partner cannot bypass the limit by distributing requests across multiple channels. Each security definition has its own independent counters - "partner-a" and "partner-b" never share a bucket, even if they call the same endpoints. There is no account-wide shared bucket where one misbehaving client can exhaust limits for everyone else.
Zato determines the client IP address using the following headers, checked in this order:
X-Zato-Forwarded-ForX-Forwarded-ForREMOTE_ADDRThe first non-empty value is used. If your deployment is behind a load balancer or reverse proxy, make sure one of these headers carries the real client address.
When IP resolution is not enough - for example, when many users share one address through mobile carriers, corporate NATs, or iCloud Private Relay and similar - use identity-aware rate limiting via security definitions instead, so the limit follows each credential rather than the shared IP.
Changes saved through the Dashboard take effect immediately, there is no need to restart the server, no propagation delay, no estimation window, and no grace period during which old rules still apply, which means you can respond to an ongoing incident by changing limits in real time.
When you click "Save", existing counters are preserved across configuration updates, so changing a limit doesn't reset the counters - if a client has used 80 of 100 allowed requests and you raise the limit to 200, they immediately have 120 remaining.

Every channel this partner authenticates to now enforces the 100/minute cap - the limit follows the credential across all endpoints.

172.16.0.0/12)Requests from that range will be silently dropped at the TCP level. You can add as many addresses per rule as needed - there is no limit on list size.

10.0.0.0/8, 172.16.0.0/12, 192.168.0.0/16)Since rules are evaluated top to bottom, internal IPs match the first rule and get through, while all other IPs hit the catch-all disallow rule and are silently dropped.

Each time range has its own independent counters. You can define as many time ranges as needed - for example, one for peak hours with generous limits, one for maintenance windows with tight limits, and the all-day range as a baseline.

Disabled rules are skipped during evaluation. You can re-enable them later without losing the configuration, and the change takes effect immediately - no need to restart anything.

This clears all counters for that rule immediately - both the per-second burst counter and the hard cap counter. The client can resume sending requests right away without waiting for a time unit to expire.
Yes. Zato's enmasse tool lets you define rate limiting rules in YAML and import them from the command line or CI/CD pipelines, without using the Dashboard at all.
Rate limiting is configured as a rate_limiting key on channel_rest and security entries. For example:
channel_rest:
- name: my.api.channel
service: my.service
url_path: /api/v1/data
rate_limiting:
- cidr_list:
- 10.0.0.0/8
time_range:
- is_all_day: false
time_from: '09:00'
time_to: '17:00'
disabled: false
disallowed: false
rate: 100
burst: 200
limit: 5000
limit_unit: hour
- cidr_list:
- 0.0.0.0/0
time_range:
- is_all_day: true
disabled: false
disallowed: false
rate: 10
burst: 20
limit: 500
limit_unit: hour
security:
- name: partner.credentials
type: basic_auth
username: partner1
rate_limiting:
- cidr_list:
- 0.0.0.0/0
time_range:
- is_all_day: true
disabled: false
disallowed: false
rate: 200
burst: 400
limit: 10000
limit_unit: day
The full YAML reference, including all supported fields and their meanings, is in the enmasse reference - point your AI assistant at that page to have it generate or modify rules for you automatically.