Skip to main content

Rate Limiting

Every Zscaler API enforces rate limits, and each product defines its own thresholds. The SDK handles rate limiting for you; you don't need to write custom retry logic, inspect headers, or tune sleep intervals. This article explains the SDK's built-in behavior and the one exception class you might want to handle.

Per-product rate limits

Limits vary by service, endpoint, and tenant. For current values, see the product-specific documentation for Business Insights, Client Connector, Cloud & Branch Connector, ZDX, ZIA, and ZPA accessed from the Understanding Rate Limiting page.

What the SDK Does Automatically

By default, every Session retries rate-limited responses without any additional code. It:

  • Retries automatically on HTTP 429 and transient 5xx responses.
  • Honors Retry-After (e.g., ZIA) and retry-after (e.g., ZPA) response headers, sleeping for exactly the duration that the service requests.
  • Falls back to exponential backoff (base 0.3s, growth factor 2) when no retry-after header is present.
  • Limits the wait time to 300 seconds per retry.
  • Retries up to three times (max_attempts) before raising an exception.

Catching ThrottledException

You only need to catch ThrottledException when you want application-specific behavior after the SDK's automatic retries are exhausted. For the common case, you can simply iterate and let the SDK handle rate limiting.

import zssdk
from zssdk.zsresource.exceptions import ThrottledException

session = zssdk.Session()

try:
# The SDK transparently retries on 429 up to max_attempts.
# If it's still rate limited after retries, this will raise.
for rule in session.zia.firewall_filtering_rules.all():
process(rule)
except ThrottledException as e:
# Application-specific handling — e.g., push work to a dead-letter queue,
# alert on-call, or back off for longer than the default.
# ThrottledException only exposes the standard SDK error attributes
# (status_code, message via str(e)); inspect those if you need more
# context, or rely on the upstream Retry-After header in your logs.
print(f"Still rate limited after retries (status {e.status_code}): {e}")

Related