In addition to
Retry-After, Sentry (Relay) also includes a special response header
X-Sentry-Rate-Limits containing a detailed list of all rate limits that apply per data category.
X-Sentry-Rate-Limits: <quota_limit>, <quota_limit>, ...
Each quota_limit has the form
retry_after:categories:scope:reason_code:... with the following parameters:
retry_after: Number of seconds (as an integer or a floating point number) until this rate limit expires.
categories: Semicolon-separated list of data categories. If empty, this limit applies to all categories. While these categories might look similar to the envelope item types, they are not identical, and have slight differences.
scope: The scope that this limit applies to. Can be ignored by SDKs.
reason_code: A unique identifier for the quota hinting at the rate limiting reason. Can be ignored by SDKs.
- More parameters can be added in the future, and can be ignored by SDKs (promise of backward compatibility).
The header may contain spaces which must be ignored. Relay will only emit spaces after
, to separate quota_limits.
Example response (formatted for readability):
HTTP/1.1 429 Too Many Requests Retry-After: 2700 X-Sentry-Rate-Limits: 60:transaction:key, 2700:default;error;security:organization
Example response (with empty categories list):
HTTP/1.1 429 Too Many Requests Retry-After: 2700 X-Sentry-Rate-Limits: 60::organization, 2700::organization
X-Sentry-Rate-Limits header may appear in any response, regardless of status code, even
200 responses. This is to proactively inform SDKs that certain payload types are disabled before SDKs even try to send them.
SDKs are expected to honor 429 responses and rate limits communicated from Sentry by stopping data transmission until the rate limit has expired. Events, transactions, sessions, and/or any other supported payload type, depending on the communicated limits, are to be discarded during the period that the rate limit is in place.
To detect rate limits in a response from Sentry, apply the following steps:
- On every response, look for
X-Sentry-Rate-Limits. If present, parse it and immediately go to Stage 2.
429responses, check for
Retry-After. Treat it like
categories=and go to Stage 2. It is allowed but not required to do this on other status codes.
429responses without the above headers, assume a 60s rate limit for all categories and go to Stage 2. See the Java implementation for reference.
- Otherwise, there are no rate limits communicated by Sentry.
Guidelines for how SDKs should determine the current rate limits:
- Rate limits must be tracked per each DSN, what corresponds to storing a rate limits map in an instance of the SDK transport/client.
- SDKs that only support one payload type can ignore
X-Sentry-Rate-Limitsand use the
Retry-Afterheader to determine rate limit expiration.
- SDKs must implement and obey limits for supported categories, for example
transaction. For each category, they should maintain a separate limit, and another separate limit for the implicit "all" category.
- SDKs must ignore dimensions they do not support or are irrelevant, for example
- Categories and scopes that are unknown to the client should be ignored. The limit still applies to the known categories. Clients should expect that more will be added in the future.
- More broadly, unknown dimensions must be ignored, that is, all additional colons and text to the right of the last parsed/interpreted dimension.
- Limits where all categories are unknown must be ignored since those limits apply to data the SDK cannot send. Do not apply unknown categories to a default category. Note that this is distinct from limits with no category, which implicitly apply to all categories (think of this as a special category).
- Always keep the maximum rate limit if multiple rate limits reference the same category. If a new rate limit is shorter than an already stored rate limit, then keep the longer one.
200 OKresponses should be treated like on 429 responses. Sentry may choose to respond with
200 OKregardless of a rate limit or may choose to inform a client proactively about a rate limit that is unrelated to the current request. This happens specifically for reject-all quotas to prevent clients from sending requests.
As stated earlier, SDKs can ignore the
scope dimension. These definitions are here as a suplement to explain what the
X-Sentry-Rate-Limits header is made of.
- Category: Classifies the type of data that is being counted. Arbitrary categories can be added as long as they can be inferred from the event or data being ingested.
While these data categories might look similar to the envelope item types, they are not identical, and have slight differences.
default: Events with an event_type not listed explicitly below.
error: Error events.
transaction: Transaction type events.
security: Events with event_type
attachment: Attachment bytes stored (unused for rate limiting)
session: Session update events
internal: a sentry/system internal eventinternal
- Scope: The unit / model in Sentry that quotas are enforced for.
- Special note on the internal data category: this data category exists but is promised not to be emitted as we do not enforcd
rate limits on internal items. This might appear odd but the purpose of this is to allow envelope implementations in SDKs to
assign a data category to internal items such as
client_report. SDKs can handle
internallike any other data category but they can rely on the fact that rate limits are not communicated for these explicitly. That said, the special all category does apply to
internalevent types as well.↩