API rate limits cap how many requests a client can send to an API within a time window, such as 100 requests per second or 10,000 per day. When an integration goes over the limit, the API rejects requests, usually with HTTP 429 Too Many Requests, until the window resets. Handling rate limits well is the difference between an integration that slows down gracefully under load and one that drops records during your busiest hour.
This guide explains how rate limits work, why integrations hit them, and the patterns that keep data flowing: backoff, batching, caching, and queue-based throttling.
How API rate limits work
Providers limit traffic to protect their systems and share capacity fairly. The common models:
| Model | How it works | Example |
|---|---|---|
| Fixed window | A set number of requests per minute, hour, or day; the counter resets on the boundary | 1,000 requests per hour |
| Sliding window | The limit applies to any rolling period, so bursts at a boundary don't double up | 100 requests in any 60 seconds |
| Token bucket | Tokens refill at a steady rate; each request spends one; bursts allowed up to the bucket size | Shopify's REST Admin API leaky-bucket model |
| Concurrency limit | A cap on requests in flight at the same time | 25 concurrent calls |
| Cost-based | Each request costs points based on complexity | GraphQL APIs that charge by query cost |
| Daily quota | A total allowance per day or per organisation | Salesforce's daily API request allocation |
Limits are often applied per API key, per user, per app, or per organisation, and sometimes all of these at once. Read each provider's documentation; Stripe, Shopify, Salesforce, HubSpot, and Google all publish their limits and response headers.
Why integrations hit rate limits
- Bulk syncs: an initial load or nightly sync sends thousands of requests in minutes.
- Fan-out: one event triggers several calls per record (look up the customer, then the order, then the invoice).
- Shared quotas: several integrations, scripts, and users draw from the same organisation-wide limit.
- Retry storms: failed requests retry immediately and add to the load that caused the failure.
- Polling: checking for changes every few seconds uses requests even when nothing has changed.
Strategies for handling rate limits
Read the headers
Most APIs tell you where you stand. Common headers include X-RateLimit-Limit, X-RateLimit-Remaining, X-RateLimit-Reset, and on a 429, Retry-After. Slow down before you hit zero, and when you get a 429 with Retry-After, wait at least that long.
Back off exponentially, with jitter
After a 429 or a temporary 5xx error, wait before retrying and double the wait each time (for example 1, 2, 4, 8 seconds), up to a maximum. Add random jitter so parallel workers don't all retry at the same moment. Stop after a set number of attempts and send the record somewhere it can be retried later.
Batch requests
Use bulk or batch endpoints where they exist: Salesforce's Bulk API, composite requests, or endpoints that accept arrays of records. One call that writes 200 records uses a fraction of the quota of 200 single calls.
Cache what rarely changes
Reference data such as product catalogues, currency lists, and user directories can be cached for minutes or hours instead of fetched on every run.
Replace polling with events
Webhooks and change events notify you when something happens, so you don't spend requests asking "anything new?" every few seconds. See what a webhook is.
Throttle through a queue
Put records in a queue and process them at a controlled rate, below the provider's limit. Throttling on your side is predictable; being throttled by the provider is not.
Rate limits during bulk loads and migrations
Initial loads and migrations are where limits bite hardest. Run them off-peak, use bulk APIs, split the load into chunks with checkpoints so a failure resumes from the last good chunk, and agree temporary limit increases with the provider if your contract allows. Keep normal daily integrations running at their usual priority while the bulk load uses what's left.
Monitoring rate-limited integrations
- Track 429 responses, retries, and records waiting to retry, per integration and per provider.
- Alert on sustained 429s, not single ones; a few are normal, a steady stream means the design needs to change.
- Watch remaining quota where providers expose it, especially daily allowances shared across teams.
- Trace each record, so you can tell whether a slow run was throttling, a downstream outage, or bad data.
Frequently asked questions
What does HTTP 429 Too Many Requests mean?
It means you've exceeded the API's rate limit for the current window. Wait before retrying, using the Retry-After header if it's provided, and reduce your request rate.
Should I retry immediately after a 429?
No. Retry after the time given in Retry-After, or with exponential backoff and jitter. Immediate retries add load and can prolong the throttling.
How do I find an API's rate limits?
Check the provider's API documentation and the response headers, such as X-RateLimit-Limit, X-RateLimit-Remaining, and X-RateLimit-Reset. Limits often differ by plan, endpoint, and whether they apply per user or per organisation.
How can I reduce the number of API calls an integration makes?
Use bulk or batch endpoints, cache reference data, switch from polling to webhooks or change events, and avoid repeated look-ups by passing data between steps.
Does upgrading to a higher API tier fix rate limiting?
It raises the ceiling but doesn't remove it. Backoff, batching, and throttling are still needed so traffic spikes and bulk loads don't cause failures.
Design for the limit, not around it
Rate limits are predictable once you plan for them: budget requests, back off politely, and make sure every throttled record gets another chance. To see how Koodisi retries and recovers throttled records, book a demo.