Rate Limits

Stream enforces rate limits to ensure the stability of our service for our customers and to encourage a performant integration. Stream powers user interactions for some of the world's largest apps and has scaling infrastructure to accommodate. Rate limits can be increased at customers' requests and by upgrading to larger usage plans.

Our default rate limits are documented below. Rate limits are higher for Enterprise plans depending on capacity and use case. Talk to your Customer Success Manager for increases.

Every Application has rate limits applied based on a combination of API endpoint and platform: these limits are set on a 1-minute time window. For example, different operations have different limits per endpoint. Likewise, different platforms such as iOS, Android or your server-side infrastructure have independent counters for each API endpoint's rate limit.

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

There are two kinds of rate limits:

  • User Rate Limits: Apply to each user and platform combination and help to prevent a single user from consuming your Application rate limits.
  • App rate limits: App rate limits are calculated per endpoint and platform combination for your application.

User Rate Limits

To avoid individual users consuming your entire quota, every single user is limited to at most 60 requests per minute (per API endpoint and platform). When the limit is exceeded, requests from that user and platform will be rejected.

App Rate Limits

Stream supports four different platforms via our official SDKs:

  • Server: SDKs that execute on the server including Node, Python, Ruby, Go, C#, PHP, and Java.
  • Android: SDKs that execute on an Android device including Kotlin, Java, Flutter, and React Native for Android clients.
  • iOS: SDKs that execute on an iOS device including Swift, Flutter, and React Native for iOS clients.
  • Web: SDKs that execute in a browser including React, Angular, or vanilla JavaScript clients.

Rate limit quotas are not shared across different platforms. This way if by accident a server-side script hits a rate limit, you will not have any impact on your mobile and web applications. When the limit is hit, all calls from the same app, platform, and endpoint will result in an error with a 429 HTTP status code.

App rate limits are administered both per minute and per second. The per-second limit is equal to the per-minute limit divided by 30 to allow for bursts.

What To Do When You've Hit a Rate Limit

You should always review responses from Stream to watch for error conditions. If you receive 429 status, this means your API request was rate-limited and you will need to retry. We recommend implementing an exponential back-off retry mechanism.

Here are a few things to keep in mind to avoid rate limits on server-side:

  1. Slow down your scripts: This is the most common cause of rate limits. You're running a cronjob or script that runs many API calls in succession. Adding a small timeout in between API calls typically solves the issue.

  2. Use batch endpoints: Batch update endpoints exist for many operations. So instead of making many calls to update one resource each, use the batch endpoint to update multiple resources in one request.

  3. Query only when needed: Sometimes apps will call a query endpoint to see if an entity exists before creating it. Many of Stream's endpoints have an upsert behaviour, so this isn't necessary in most cases.

  4. If rate limits are still a problem, Stream can set higher limits for certain pricing plans:

  • For Standard plans, Stream may also raise rate limits in certain instances. An integration review is required to ensure your integration is making optimal use of the default rate limits before any increase will be applied.
  • For Enterprise plans, Stream will review your architecture, and set higher rate limits for your production application.

Rate limit headers

API responses include rate limit information in headers.

HeaderDescription
X-RateLimit-Limitthe total limit allowed for the resource requested (i.e. 5000)
X-RateLimit-Remainingthe remaining limit (i.e. 4999)
X-RateLimit-Resetwhen the current limit will reset (Unix timestamp)

const response = await client....
const rateLimit = response.metadata.rateLimit;
// the total limit allowed for the resource requested
console.log(rateLimit.rateLimit);
// the remaining limit
console.log(rateLimit.rateLimitRemaining);
// when the current limit will reset - Date
console.log(rateLimit.rateLimitReset);
// or
try {
  await client....
} catch (error) {
  const rateLimit = error.metadata?.rateLimit;
  if (error.metadata?.responseCode === 429) {
    // Wait until rate limit resets and then retry
  }
}

Inspecting rate limits

Stream offers the ability to inspect an App's current rate limit quotas and usage in your App's dashboard. Alternatively, you can also retrieve the API limits for your application using server-side SDKs:

// 1. Get feeds rate limits, server-side platform
const limits = await client.feeds.getFeedsRateLimits({ server_side: true });

// 2. Get feeds rate limits, all platforms
const limits = await client.feeds.getFeedsRateLimits();

// 3. Get feeds rate limits, iOS and Android
const limits = await client.feeds.getFeedsRateLimits({
  ios: true,
  android: true,
});

// 4. Get feeds rate limits for specific endpoints
const limits = await client.feeds.getFeedsRateLimits({
  endpoints: "QueryActivities,AddActivity,GetOrCreateFeed",
});

// Get rate limits (all platforms, common and moderation endpoints)
const rateLimits = await client.getRateLimits();

Default rate limits by endpoint

Feeds endpoints

Operation IDRate limit (req/min)
AcceptFeedMemberInvite1,000
AcceptFollow1,000
ActivityFeedback1,000
AddActivity1,000
AddActivityReaction1,000
AddBookmark1,000
AddComment1,000
AddCommentReaction1,000
AddCommentsBatch300
CastPollVote1,000
CreateCollections300
CreateFeedGroup300
CreateFeedsBatch300
CreateFeedView300
CreateMembershipLevel300
DeleteActivity1,000
DeleteActivityReaction1,000
DeleteActivities300
DeleteBookmark1,000
DeleteBookmarkFolder1,000
DeleteComment1,000
DeleteCommentReaction1,000
DeleteFeed1,000
DeleteFeedsBatch300
DeleteFeedGroup300
DeleteFeedUserData300
DeleteFeedView300
DeleteMembershipLevel300
DeletePollVote1,000
ExportFeedUserData300
Follow1,000
FollowBatch300
GetActivity1,000
GetComment1,000
GetCommentReplies1,000
GetComments1,000
GetFeedGroup1,000
GetFeedView1,000
GetFeedVisibility1,000
GetFeedsRateLimits1,000
GetFollowSuggestions1,000
GetOrCreateFeed10,000
GetOrCreateFeedGroup300
GetOrCreateFeedView300
GetOrCreateFollows1,000
GetOrCreateUnfollows1,000
ListFeedGroups1,000
ListFeedViews1,000
ListFeedVisibilities1,000
MarkActivity1,000
PinActivity1,000
QueryActivities1,000
QueryActivityReactions1,000
QueryBookmarkFolders1,000
QueryBookmarks1,000
QueryCommentReactions1,000
QueryComments1,000
QueryFeedMembers1,000
QueryFeeds1,000
QueryFollows1,000
QueryMembershipLevels1,000
QueryFeedsUsageStats300
ReadCollections300
RejectFeedMemberInvite1,000
RejectFollow1,000
RestoreActivity300
StopWatchingFeed1,000
Unfollow1,000
UnfollowBatch300
UnpinActivity1,000
UpdateActivity1,000
UpdateActivityPartial1,000
UpdateActivitiesPartialBatch300
UpdateBookmark1,000
UpdateBookmarkFolder1,000
UpdateComment1,000
UpdateFeed1,000
UpdateFeedGroup300
UpdateFeedMembers1,000
UpdateFeedView300
UpdateFeedVisibility1,000
UpdateFollow1,000
UpdateMembershipLevel1,000
UpsertActivities300
UpsertCollections300

Common endpoints

These endpoints are shared among all Stream products:

Operation IDRate limit (req/min)
BlockUsers300
CheckExternalStorage60
CheckPush60
CheckSNS60
CheckSQS300
CreateBlockList60
CreateDevice300
CreateExternalStorage60
CreateGuest1,000
CreateImport300
CreateImportURL300
CreateImportV2Task1,000
CreatePoll300
CreatePollOption300
CreateRole60
Connect10,000
DeactivateUser60
DeactivateUsers60
DeleteBlockList60
DeleteDevice60
DeleteExternalStorage60
DeleteFile60
DeleteImage60
DeleteImportV2Task1,000
DeletePoll60
DeletePollOption60
DeletePushProvider60
DeleteRole60
DeleteUsers6
ExportUser60
ExportUsers60
GetApp10,000
GetBlockList60
GetBlockedUsers300
GetImport300
GetImportV2Task1,000
GetOG1,000
GetPermission60
GetPoll1,000
GetPollOption1,000
GetPushTemplates60
GetRateLimits1,000
GetTask300
GetUserLiveLocations1,000
ListBlockLists60
ListDevices60
ListExternalStorage60
ListImportV2Tasks1,000
ListImports300
ListPermissions60
ListPushProviders60
ListRoles60
LongPoll10,000
QueryPollVotes1,000
QueryPolls1,000
QueryUsers1,000
ReactivateUser60
ReactivateUsers60
RestoreUsers1,000
UnblockUsers300
UpdateApp60
UpdateBlockList60
UpdateExternalStorage60
UpdateLiveLocation1,000
UpdatePoll300
UpdatePollOption300
UpdatePollPartial300
UpdatePushNotificationPreferences300
UpdateUsers300
UpdateUsersPartial300
UploadFile1,000
UploadImage1,000
UpsertPushProvider60
UpsertPushTemplate60