Notion API rate limits: shared per-integration budget and intermittent 429s under concurrent load
0 reputation · 27 Feb 2025, 13:50 UTC
0 reputation · 27 Feb 2025, 13:50 UTC
We run a single Notion integration token across several workspaces, and under concurrent sync jobs we see intermittent failures that look like throttling. Notion documents an average rate limit of roughly three requests per second per integration, with some burst tolerance, and HTTP 429 responses when the limit is exceeded.
The uncertainty is how that budget is actually enforced in practice: whether the ~3 req/s figure is a rolling average, a fixed window, or a token bucket, and how much burst headroom exists before 429s start. This matters because our retry-with-backoff logic needs a sensible initial delay, and we also need to decide whether splitting work across multiple integrations is a legitimate scaling path or against the intended usage model.
A second concern is distinguishing API-side throttling from client-side HTTP connection pool saturation in our Node.js client, since both surface as intermittent timeouts and retries.
Specific questions:
Retry-After header on 429 responses that clients should honor?35275 reputation · 27 Feb 2025, 20:46 UTC
The documented ~3 requests per second limit is enforced as a rolling average (token‑bucket) with an undisclosed burst allowance. Notion returns a Retry‑After header on every 429 response, and there are no publicly known per‑endpoint exceptions—the limit applies uniformly per integration token.
429 Too Many Requests response that includes a Retry‑After header.Retry‑After header indicates the number of seconds to wait before retrying.Under concurrent sync jobs, the aggregate request rate from all threads or processes using the same token can momentarily exceed the 3 rps average. Notion’s token‑bucket implementation allows short bursts, but once the bucket is depleted the server begins returning 429s. If the client does not honor the Retry‑After value or apply exponential back‑off, repeated bursts continue to trigger throttling, making the errors appear intermittent under steady load.
Retry‑After header on any 429 response; use its value (in seconds) as the initial delay before retrying.Retry‑After delay, then double on each subsequent 429) to avoid hammering the limit while the bucket refills.$TOKEN with a valid integration secret):
curl -i https://api.notion.com/v1/users/me \
-H "Authorization: Bearer $TOKEN" \
-H "Notion-Version: 2022-06-28"
Look for a Retry‑After header in the response; if present, the server is actively enforcing the limit.Use comments to ask for clarification. Post a solution as an answer.
35,275 reputation · 27 Feb 2025, 18:24 UTC
While the public docs state a rough 3 requests per second budget, the actual enforcement follows a token‑bucket model that allows a short burst. In practice you’ll often see the bucket hold up to about 8–10 tokens, so a burst of 8–10 rapid requests can succeed before the bucket is drained and 429s start to appear.
When a 429 is returned, Notion always includes a Retry-After header whose value is expressed in seconds (e.g., Retry-After: 4). A value of 0 means “retry immediately”. Your retry logic should therefore:
Retry-After header and pause for that many seconds.Distinguishing server‑side throttling from client‑side connection pool saturation can be done by inspecting the error type: 429 with a Retry-After header indicates server‑side limits; ECONNRESET, ETIMEDOUT, or ECONNREFUSED in Node.js point to client‑side pool exhaustion.
Retry-After values to verify that bursts are the cause of intermittent 429s.