
An integration can be correctly authenticated, well tested, and still become unreliable when it sends requests faster than a connected service allows. A CRM sync may work during a quiet test and then stall when a larger import begins. A reporting job may retry a busy endpoint so aggressively that it creates more pressure instead of recovering.
Rate limits are a normal part of API design. They protect a service from uneven traffic and give its operator a way to manage capacity. For a small business, the practical goal is not to eliminate limits. It is to make the integration aware of them, pace its work, and give people a clear path when work must wait.
Start by finding the real constraint
Before writing retry code, document how the service limits requests. The limit may apply per user, API credential, tenant, IP address, endpoint, or resource. It may be a number of requests per minute, a concurrent-request ceiling, a daily allowance, or a variable cost based on the size of the response. Two endpoints in the same service may not share the same rule.
Read the provider’s documentation and inspect normal responses for useful headers. Some APIs expose remaining capacity or a reset time. Treat those values as guidance from the service, not as a promise that every request will succeed. Limits can change by plan, workload, or operational condition.
Also estimate your own traffic. List the workflows that call the integration, their normal batch size, and what happens when several jobs overlap. This often reveals that the problem is local: a loop makes one request per row, several workers process the same queue at once, or a user action starts a second sync before the first has finished.
Put pacing at the integration boundary
A local rate limiter gives your application a controlled place to slow down before the provider has to reject work. Depending on the workflow, it might use a token-bucket or leaky-bucket approach, a concurrency limit, a queue with a worker, or a simple scheduled batch. The right choice depends on whether work is interactive, time-sensitive, or safe to delay.
Keep the limiter close to the outbound client so every caller follows the same rule. If one background job respects a limit but an administrative script bypasses it, the provider still sees the combined traffic. A shared limiter is especially important when several application processes or workers use the same credential.
Use the smallest useful design first. For a nightly inventory sync, a queue with one or a few workers and a documented maximum request rate may be enough. For a user waiting on a single lookup, a short timeout and a clear retry decision may be more appropriate. Do not turn every API call into an elaborate distributed system before the traffic pattern requires it.
Treat 429 as a scheduling signal
HTTP 429 means the client has sent too many requests in a given period. RFC 6585 says the response should explain the condition and may include a Retry-After header. MDN also notes that limits may be server-wide or specific to a resource, user, or application.
When a 429 arrives, first record enough context to diagnose it: the endpoint, operation type, status code, request correlation ID if provided, and a redacted form of the provider’s rate-limit headers. Do not log access tokens or complete business payloads merely to understand the throttle.
Honor a valid Retry-After value when the operation is safe to retry. If the service does not provide one, use a bounded backoff policy with a maximum wait and a maximum number of attempts. Add jitter so multiple workers do not wake at the same instant and recreate the spike. A retry is a scheduling choice, not an instruction to keep trying forever.
Separate retryable work from work that needs review
A temporary rate limit is different from an invalid request, an expired authorization, or a business rule violation. Retry only conditions that are plausibly temporary and safe to repeat. A 429 or brief network timeout may qualify; a malformed record usually does not.
Keep accepted work in a durable job or queue record while it waits. Store its status, next-attempt time, attempt count, and a safe error category. If the limit persists beyond the retry budget, move the work to a reviewable failed state. An operator should be able to see what was delayed, why, and what action is available.
This matters for business workflows. If a customer import is partially processed, the system should distinguish accepted, completed, skipped, and waiting records. A generic success message hides work that still needs attention, while a generic failure message makes a recoverable throttle look like data loss.
Reduce avoidable request pressure
Retries are only one part of the solution. Review whether the integration is asking for more data than it needs. Use pagination, field selection, incremental synchronization, and provider-supported batch operations when they fit the API contract. Cache stable reference data when freshness allows it. Coalesce duplicate requests that arrive close together.
Be careful with batching: a larger request may reduce request count but increase processing time, payload size, or the cost of one failure. Choose a batch size you can validate, retry, and reconcile. The best batch is not necessarily the largest one.
Monitor the experience, not just the error count
Track request volume, 429 rate, retry count, time spent waiting, queue age, completed work, and permanently failed work by workflow. A low 429 count can still be a poor experience if every request waits through a long retry. A rising queue age may matter more than a short-lived spike in errors.
Set alerts around actions: a queue has exceeded its normal age, the retry budget is being exhausted, or the provider’s remaining-capacity signal is consistently low. Give the workflow an owner who can pause a sync, reduce concurrency, contact the provider, or review a failed record.
A practical first implementation
- List each outbound workflow and the credential or tenant it uses.
- Document provider limits, response headers, and safe retryable statuses.
- Centralize outbound calls behind a client with pacing and redacted structured logs.
- Start with conservative concurrency and a bounded, jittered backoff.
- Persist waiting work and expose status that distinguishes accepted from complete.
- Test a 429 response, a missing
Retry-Afterheader, a worker restart, and a permanently invalid record. - Review queue age, retry behavior, and business impact before increasing throughput.
Rate limiting becomes manageable when it is treated as part of the integration’s operating design. A small business does not need to predict every provider incident. It needs a clear boundary that paces requests, preserves work, communicates honestly, and gives a person enough evidence to decide what happens next.
Next step: Schedule a short consultation to identify the next useful improvement.