Designing for API rate limits: budgets, back-off, and backfills that do not starve production
Published 10 March 2026Updated 19 August 20268 min read
Treat a vendor's rate limit as a shared, finite budget with named consumers. Give real-time traffic priority, cap backfills in a separate lane, use exponential back-off with jitter on 429 and 5xx, and respect retry-after headers. Uncoordinated per-worker retries turn a partial degradation into a full outage.
One budget, many consumers
Vendor limits apply per account, not per process. If four workers each implement their own limiter, the effective limit is exceeded four times over. Centralise the budget — a shared token bucket — and give each consumer a named allocation.
Back-off correctly
- Respect retry-after when the provider sends it; it is authoritative.
- Use exponential back-off with full jitter, otherwise every client retries in lockstep and re-creates the spike.
- Cap attempts and dead-letter the rest; infinite retry is a self-inflicted denial of service.
- Distinguish retryable errors from permanent ones. Retrying a 422 forever accomplishes nothing.
Backfills need their own lane
A one-off historical load will consume the entire budget if allowed. Run it at low priority with an explicit ceiling, checkpointed so it can be paused and resumed without restarting, and schedule it outside the peak window of the vendor's own limits.
Observe the budget
Emit consumed budget, 429 count, retry depth, and queue backlog age as metrics. Backlog age is the leading indicator: it rises before anything visibly breaks, which is exactly when intervention is cheap.
Frequently asked questions
What is the correct retry strategy for a 429 response?
Honour retry-after if present, otherwise exponential back-off with full jitter, bounded attempts, and a dead-letter path. Coordinate the back-off across workers so they do not all retry simultaneously.
How do you run a large backfill without breaking production sync?
Give the backfill its own low-priority lane with a capped share of the shared request budget, checkpoint progress so it can pause and resume, and run it outside peak hours.
Should retries be handled in the application or the queue?
In the queue, with the handler kept idempotent. Application-level retry loops hold connections open, hide failures from metrics, and multiply load during incidents.
How to build webhook consumers that survive retries, duplicates, and outages
A production checklist for webhook receivers: signature verification, idempotency keys, ordering, replay, dead-letter handling, and the observability that makes failures visible.
Zoho integration patterns: CRM, Books, and Desk without the spreadsheet in the middle
How to integrate Zoho CRM, Zoho Books, and Zoho Desk with products, databases, and payment providers: API surfaces, OAuth, metered billing, and month-end close safety.
ServiceNow integration patterns for engineering teams
Table API versus Scripted REST, incident bridging, CMDB alignment, SLA-safe state mapping, and loop suppression when connecting ServiceNow to engineering tooling.