// Server-side platform only
const limits = await client.getRateLimits({ serverSide: true });
// All platforms
const limits = await client.getRateLimits();
// Specific platforms
const limits = await client.getRateLimits({ ios: true, android: true });
// Specific endpoints
const limits = await client.getRateLimits({
endpoints: ["QueryUsers", "UpdateUsers"],
});Rate limits
Stream applies rate limits to protect both your application and our infrastructure. Rate limits prevent:
- Integration issues or abuse from degrading your app's performance (excessive API calls trigger client-side events)
- Resource consumption beyond what is provisioned for your plan
- Common integration mistakes, such as opening multiple WebSocket connections per user
Rate limits work the same way across every Stream product. They are applied per API endpoint and platform on a 1-minute window. Different platforms (iOS, Android, Web, Server) have independent counters for each endpoint.
If 6,000 iOS users and 6,000 Android users connect within one minute, no rate limit is triggered. The 10,000/minute connect limit applies independently to each platform.
Dynamic Rate Limiting: Rate limits may be adjusted based on overall platform load and your application's individual usage patterns for query endpoints. During periods of high demand, the platform may temporarily reduce rate limits to ensure stability and fair resource allocation for all users. Monitor the X-RateLimit-* headers in API responses to track your current limits.
Types of Rate Limits
User Rate Limits
Each user is limited to 60 requests per minute per endpoint and platform. This prevents a single user from consuming your entire application quota. Your server is not subject to user rate limits.
App Rate Limits
App rate limits apply per endpoint and platform combination. Stream supports four platforms:
| Platform | SDKs |
|---|---|
| Server | Node, Python, Ruby, Go, C#, PHP, Java |
| Android | Kotlin, Java, Flutter, React Native |
| iOS | Swift, Flutter, React Native |
| Web | React, Angular, JavaScript |
Rate limits are not shared across platforms. If a server-side script hits a rate limit, your mobile and web applications are unaffected.
App rate limits are enforced both per minute and per second. The per-second limit equals the per-minute limit divided by 30 to allow for bursts.
When a rate limit is exceeded, all calls from the same app, platform, and endpoint return HTTP status 429.
Rate Limit Headers
All API responses include rate limit information in headers.
| Header | Description |
|---|---|
| X-RateLimit-Limit | Total limit for the requested resource (e.g. 5000) |
| X-RateLimit-Remaining | Remaining requests in current window (e.g. 4999) |
| X-RateLimit-Reset | When the current window resets (Unix timestamp) |
Inspecting Rate Limits
Check your current rate limit quotas and usage in your app's dashboard, or via the API.
The response includes the 1-minute limit, remaining quota, and window reset timestamp.
Handling Rate Limit Errors
When you receive a 429 status code, implement exponential back-off retry logic. Use the X-RateLimit-Reset header to determine when to retry.
Catching 429s in backend SDKs
The Go, Python, Java, PHP, Ruby, and .NET SDKs surface 429s as a dedicated rate-limit exception that carries the parsed Retry-After header. Catch the rate-limit subclass first if you want to react to throttling, then fall through to the broader API-error catch for other 4xx/5xx responses. Each SDK documents its exception class hierarchy for this purpose. In Node.js, check the response code and rate limit information on the error's metadata instead.
try {
await client.queryUsers(...);
} catch (error) {
const rateLimit = error.metadata?.rateLimit;
if (error.metadata?.responseCode === 429) {
// Wait until rateLimit.rateLimitReset, then retry
}
}Retry-After parsing supports both forms documented in RFC 7231 §7.1.3: an integer number of seconds (Retry-After: 30) or an HTTP-date (Retry-After: Fri, 31 Dec 2026 23:59:59 GMT). Past dates clamp to zero. If the header is absent or unparseable, the exception's retryAfter field is null/None/zero so your code does not have to guard against parse errors.
Automatic retries
Instead of catching 429s yourself, you can let the SDK retry them for you. Automatic retries are opt-in and disabled by default; enable them when you construct the client and set the attempt budget and the maximum wait between attempts.
from getstream import Stream, RetryConfig
client = Stream(
api_key="your_api_key",
api_secret="your_api_secret",
retry=RetryConfig(enabled=True, max_attempts=3, max_backoff=30.0),
)When enabled, the SDK retries only idempotent GET and HEAD requests, and only when the response is a 429 that the backend has not marked unrecoverable, or a transport-level failure (connection reset, timeout, DNS, or TLS). Writes (POST, PUT, PATCH, DELETE), 5xx responses, and other 4xx responses are never retried. maxAttempts counts the initial request, so the default of 3 means one request plus up to two retries. Between attempts the SDK waits for the Retry-After header when present (clamped to maxBackoff), otherwise a full-jitter exponential backoff capped at maxBackoff. If every attempt fails, the last error is surfaced unchanged, so the exception handling above still applies.
Avoiding Rate Limits
-
Add delays to scripts - The most common cause of rate limits. Add timeouts between successive API calls in batch scripts or cronjobs.
-
Use batch endpoints - Instead of 100 individual calls, use batch endpoints to update multiple resources in one request.
-
Check client-side rendering logic - Infinite pagination bugs or other client-side issues can trigger excessive API calls.
-
Avoid redundant queries - Many of Stream's endpoints have upsert behavior. Do not query to check whether an entity exists before creating it.
Each product's rate limits page lists practices specific to that product, such as livestream chat messaging volume.
Requesting Higher Limits
- Standard plans - Stream may increase limits after reviewing your integration to confirm optimal usage of default limits.
- Enterprise plans - Stream reviews your architecture and sets appropriate limits for your production application.
Default Limits by Endpoint
Default limits for endpoints shared by all Stream products are listed below. Product endpoints are documented with each product:
Common endpoints
| Operation ID | Rate limit (req/min) |
|---|---|
| BlockUsers | 300 |
| CheckExternalStorage | 60 |
| CheckPush | 60 |
| CheckSNS | 60 |
| CheckSQS | 300 |
| CreateBlockList | 60 |
| CreateDevice | 300 |
| CreateExternalStorage | 60 |
| CreateGuest | 1,000 |
| CreateImport | 300 |
| CreateImportURL | 300 |
| CreateImportV2Task | 1,000 |
| CreatePoll | 300 |
| CreatePollOption | 300 |
| CreateRole | 60 |
| Connect | 10,000 |
| DeactivateUser | 60 |
| DeactivateUsers | 60 |
| DeleteBlockList | 60 |
| DeleteDevice | 60 |
| DeleteExternalStorage | 60 |
| DeleteFile | 60 |
| DeleteImage | 60 |
| DeleteImportV2Task | 1,000 |
| DeletePoll | 60 |
| DeletePollOption | 60 |
| DeletePushProvider | 60 |
| DeleteRole | 60 |
| DeleteUsers | 6 |
| ExportUser | 60 |
| ExportUsers | 60 |
| GetApp | 10,000 |
| GetBlockList | 60 |
| GetBlockedUsers | 300 |
| GetImport | 300 |
| GetImportV2Task | 1,000 |
| GetOG | 1,000 |
| GetPermission | 60 |
| GetPoll | 1,000 |
| GetPollOption | 1,000 |
| GetPushTemplates | 60 |
| GetRateLimits | 1,000 |
| GetTask | 300 |
| GetUserLiveLocations | 1,000 |
| ListBlockLists | 60 |
| ListDevices | 60 |
| ListExternalStorage | 60 |
| ListImportV2Tasks | 1,000 |
| ListImports | 300 |
| ListPermissions | 60 |
| ListPushProviders | 60 |
| ListRoles | 60 |
| LongPoll | 10,000 |
| QueryPollVotes | 1,000 |
| QueryPolls | 1,000 |
| QueryUsers | 1,000 |
| ReactivateUser | 60 |
| ReactivateUsers | 60 |
| RestoreUsers | 1,000 |
| UnblockUsers | 300 |
| UpdateApp | 60 |
| UpdateBlockList | 60 |
| UpdateExternalStorage | 60 |
| UpdateLiveLocation | 1,000 |
| UpdatePoll | 300 |
| UpdatePollOption | 300 |
| UpdatePollPartial | 300 |
| UpdatePushNotificationPreferences | 300 |
| UpdateUsers | 300 |
| UpdateUsersPartial | 300 |
| UploadFile | 1,000 |
| UploadImage | 1,000 |
| UpsertPushProvider | 60 |
| UpsertPushTemplate | 60 |
All endpoints also enforce the user rate limit of 60 requests per minute per user. Rate limits can be adjusted based on your use case and plan.