You've scheduled a quiet background sync against a B2B data API. It runs reliably in testing, then a configuration change makes several workers fire at once. The API starts returning 429 Too Many Requests, records arrive late, and the dashboard looks incomplete before anyone realizes the problem is request volume.
That's the practical side of an API rate limit. It isn't just a number in documentation. It's a traffic rule that shapes how your workers, queues, retries, and tenant workloads interact with a shared system. Once you understand what the limit measures and how the server enforces it, you can design integrations that slow down safely instead of failing noisily.
Table of Contents
- The Moment a Quiet Job Brings Down an Integration
- What an API Rate Limit Actually Means
- How Servers Enforce Rate Limits Behind the Scenes
- Ways Limits Are Measured and Applied
- Handling 429 Errors Without Triggering Retry Storms
- Cost-Aware Limits for B2B Data APIs
- Rate Limits as a Fairness Contract Between Client and Server
The Moment a Quiet Job Brings Down an Integration
The job looked harmless. A scheduler launched a synchronization task every minute, and each task fetched records from a B2B data API. The worker pool had been tuned for normal traffic, so nobody expected trouble from a routine configuration update.
Then the update changed concurrency. Instead of processing work in a controlled stream, the job released 500 parallel calls after each scheduled trigger. The API accepted traffic initially, but within ten minutes the integration began receiving HTTP 429 responses. Those figures describe the engineering scenario, not a measured platform result.
The failure didn't look like a server crash. Workers kept running. The queue kept accepting messages. The first visible symptoms were missing rows, delayed dashboards, and a pager alert that fired only after users reported stale results. A retry loop made the situation worse because each failed request returned to the queue and competed with new work.
Practical rule: Background work needs a traffic budget just as much as an interactive endpoint does.
Teams often misunderstand rate limits. They protect the foreground path, then let cron jobs, queue consumers, enrichment pipelines, and AI agent workflows run without coordination. A workload can be valid and authenticated, yet still exceed the rate a provider allows at a particular moment.
The useful questions are concrete:
- How can you tell whether the server has imposed a limit?
- Does the cap apply per account, IP, endpoint, or operation cost?
- Should a worker wait, retry, or move the task back to a queue?
- How do you prevent multiple pods from retrying together?
- When does request count stop being a fair way to measure usage?
The answers start with the protocol signal, then move into algorithms, measurement scope, retry design, and cost-aware policies for B2B data APIs.
What an API Rate Limit Actually Means
Think of a coffee shop with two registers and a line at the door. The manager wants every customer served, but one customer can't walk up and place an unlimited number of orders at once. The shop caps the customer's order flow so the registers can keep serving everyone.
An API rate limit applies the same idea to software. It's a server-side rule that restricts how many requests a client can make during a defined period. The client might be identified by an API key, account token, IP address, tenant, route, or a combination of those attributes.
The formal protocol signal is HTTP 429 Too Many Requests. RFC 6585 introduced status code 429 in April 2012, filling a gap in the original HTTP/1.1 specification from 1999, which had no dedicated status code for rate-limited clients. RFC 6585 also says 429 responses shouldn't be stored by caches and may include Retry-After.
Read the response before choosing an action
A rate-limited response can tell your client what to do next:
HTTP/1.1 429 Too Many Requests
Retry-After: 30
X-RateLimit-Remaining: 0
Retry-After can express a delay in seconds or an HTTP date, as described in the HTTP rate-limit header guidance. X-RateLimit-Remaining is a commonly used convention that indicates how much capacity remains in the current limit window. Header names vary, so your client should follow the provider's documentation rather than assume every API uses the same vocabulary.
A rate limit controls request flow over time, such as requests per second or requests per minute. A quota controls total consumption over a longer accounting period, such as a billing cycle. A worker can be below its short-term rate limit while approaching its monthly quota, or stay within its quota while sending a burst that triggers a 429.
How Servers Enforce Rate Limits Behind the Scenes
The same published cap can behave very differently depending on the enforcement algorithm. The algorithm determines whether the server tolerates bursts, smooths traffic, or counts requests inside discrete intervals.
Four common algorithms
Fixed window divides time into fixed intervals and counts requests inside each one. A policy of 100 requests per minute could accept 100 requests at the end of one minute and another 100 at the start of the next, allowing up to 200 requests across two adjacent seconds if the boundary lines up. That edge burst is simple to implement, but it can surprise downstream systems.
Sliding window evaluates a moving period instead of resetting everything at a hard boundary. The server considers recent request history continuously, which reduces the sharp edge created by fixed windows. It generally offers a fairer view of recent traffic, although it requires more tracking.
Token bucket starts with a bucket of tokens. Requests consume tokens, and tokens refill at a steady rate. A client can spend the accumulated tokens in a short burst, then must wait for replenishment. This pattern is common when an API wants to support interactive bursts while controlling the average flow. Docebo's handling guidance describes the pattern and notes that some implementations don't return retry or remaining-quota headers.
Leaky bucket places incoming requests into a queue and drains them at a fixed output rate. It smooths traffic before work reaches a database, enrichment service, or another constrained dependency. The trade-off is queue delay, plus rejection when the queue can't accept more work.
| Algorithm | How It Counts | Example Limit | Burst Behavior | Best Fit |
|---|---|---|---|---|
| Fixed window | Counts requests in discrete intervals | 100 requests per minute | Boundary bursts can occur | Simple policies |
| Sliding window | Counts recent requests in a moving interval | 100 requests over a rolling minute | Smoother than fixed windows | Fairer production controls |
| Token bucket | Spends and refills tokens | 100-token bucket with a refill rate | Allows short bursts | Interactive APIs |
| Leaky bucket | Queues and drains requests steadily | Fixed output rate | Converts bursts into queueing | Protecting downstream services |
The counter needs a shared home
A single server can keep counters in memory, but that approach breaks down when several application nodes receive traffic for the same client. One node may think the client has capacity while another has already counted the limit.
Distributed deployments commonly use Redis or another shared store for counters. The design still involves trade-offs around latency, consistency, expiration, and regional traffic. If your application collects public information through a B2B data API, the same discipline applies to your own workers. Treat request shaping as part of the integration architecture, alongside queue design and data normalization. See web data collection architecture for related integration considerations.
Ways Limits Are Measured and Applied
A limit isn't meaningful until you know who shares the counter. A cap attached to an account token gives one result. The same cap attached to an IP address or one expensive endpoint produces a different fairness policy.
Cloudflare publishes multiple examples, including 1,200 requests per 5 minutes per client API user or account token and 200 requests per second per IP, documented in its HTTP 429 troubleshooting guidance. GitHub's public rate-limit endpoint shows 60 core API requests and 10 search requests for unauthenticated requests, as documented in GitHub's rate-limit API reference.
| Scope | What shares the counter | Advantage | Common fairness problem |
|---|---|---|---|
| Per user or account token | Requests authenticated as one identity | Aligns usage with ownership | One busy account can consume its allowance quickly |
| Per IP | Requests from the same network address | Useful before authentication | Shared offices and NAT gateways can combine unrelated users |
| Per endpoint | Calls to one route or operation | Protects expensive paths such as search or bulk export | Clients may need to track several budgets |
| Per tenant | All workloads belonging to one customer | Isolates multi-tenant usage | Requires reliable tenant identification |
A 5,000-request-per-hour policy can also behave differently depending on its clock. A fixed reset can create a rush near the boundary, while a continuously moving window spreads enforcement across time. The scope matters just as much. A global account limit may let a cheap read consume capacity needed by a costly search route, while endpoint-specific counters keep those workloads separate.
Per-IP controls can penalize users behind shared networks because the server sees one address for several actors. Per-key controls usually provide cleaner accountability for authenticated clients. Per-endpoint controls make sense when a search, export, or aggregation operation consumes more backend work than a simple lookup.
That makes measurement granularity a fairness decision, not just a technical setting. The question is who should compete for capacity, and whether two requests should consume the same allowance.
Handling 429 Errors Without Triggering Retry Storms
A 429 response is a coordination signal. Your client shouldn't treat it like a generic network failure and immediately send the same request again.
Start by inspecting Retry-After and any remaining-quota headers. If the server gives a delay, use it as the earliest retry time. If the response provides no useful timing, apply a local policy with a bounded retry count, a queue deadline, and backoff.

Separate immediate work from deferred work
An immediate retry is appropriate only when the server indicates that capacity is available or the operation is safe to repeat without delay. A 429 generally points in the opposite direction. Repeating at once makes the client part of the overload.
Exponential backoff increases the wait after each failed attempt. A simple policy doubles the delay after each 429. Jitter adds a random variation to that delay, so several application pods don't wake up at the same instant.
Without jitter, hundreds of workers can all receive a 429, sleep for the same duration, and retry together. That synchronized wave creates a retry storm, which adds load just as the upstream service is recovering. The Retry-After guidance for 429 responses explains why honoring the server hint and combining it with exponential backoff and jitter helps avoid secondary spikes.
A circuit breaker adds another safety layer. After repeated failures cross your locally chosen threshold, the breaker stops sending new calls for a cooling period. It then permits a small probe before reopening normal traffic. This gives the upstream service time to drain rather than forcing every worker to test it continuously.
A budget-aware retry loop can follow this shape:
- Check the local token bucket before sending.
- Send the request and inspect the status.
- On 429, parse
Retry-Afterif present. - Calculate the larger of the server delay and local exponential backoff.
- Add jitter, then check the job deadline.
- Requeue the work if the deadline or retry budget is exhausted.
- Open the circuit when repeated failures indicate broader pressure.
Your queue should preserve enough context to retry safely, including the operation identity and attempt count. Don't let a retry create duplicate records or repeat a non-idempotent action without an idempotency design.
A synchronous integration can still use these controls, but a long-running extraction or enrichment workflow may fit an asynchronous pattern better. The distinction between those delivery models is outlined in synchronous and asynchronous API workflows.
Cost-Aware Limits for B2B Data APIs
A flat request count assumes every request costs the same. That assumption fails when one endpoint performs a quick read while another runs joins, third-party lookups, enrichment, search, or machine-learning inference.
A weighted policy can assign different token costs to different operations. For example, a simple endpoint might cost 1 token, a richer operation 5 tokens, and a high-cost aggregation 20 tokens. Those weights are an illustrative policy model, not a universal standard.
Compare that with a naive 1,000 calls per day cap. A client could spend the entire allowance on one bulk export, even if another client uses the same number of calls for small reads. The call counts match, but the compute, latency, downstream usage, and operational impact may not.

Translate system cost into client-visible policy
Cost-aware limiting works best when the provider explains what consumes capacity. A request can be charged against a weighted budget before expensive work starts, or the system can account for actual operation characteristics after classification. The policy should remain predictable enough that customers can plan workers and budgets.
A 429 doesn't always mean the client behaved badly. It can mean the requested operation would push the tenant beyond its contracted compute allowance, or that a costly route has no available capacity at that moment. The response still needs actionable retry guidance, because the consumer must know whether to wait, reduce concurrency, choose a cheaper endpoint, or move the job to asynchronous processing.
The cost-aware API rate limiting guidance highlights why request count alone can be too crude for expensive and bursty workloads. It also points toward separate controls for costly operations and layered per-user or per-endpoint policies.
For consumers, the practical change is simple: track cost-weighted usage, not only calls. Record endpoint, tenant, operation type, response status, retry count, and consumed units. A dashboard that shows request count but hides weighted usage can make a customer believe capacity remains when the expensive budget is already nearly exhausted.
If your product needs company firmographics or related enrichment workflows, document the operation classes before you build concurrency around them. A company enrichment API can serve different workloads with very different backend profiles, so a single request counter may not describe the cost.
Rate Limits as a Fairness Contract Between Client and Server
A rate limit is easier to understand when you treat it as a contract. The server promises to accept traffic within a documented policy. The client promises to identify itself correctly, pace requests, honor retry guidance, and avoid turning temporary rejection into a larger outage.
That contract protects quiet tenants from noisy neighbors. In a shared system, one customer's bursty loop can consume database connections, compute, queue capacity, or downstream provider allowance that other customers need. A published cap gives the provider a mechanism to isolate that behavior before it starves the rest of the platform.

Transparency turns a limit into an engineering input
Clear limits help customers size worker pools and forecast usage. Clear 429 responses help them decide whether to wait, reduce concurrency, or schedule work later. If the provider exposes remaining capacity and reset information, the client can make those choices programmatically instead of discovering the policy through repeated failures.
The alternative is operational guesswork. A team sends requests at full speed, treats every rejection as a temporary inconvenience, and lets multiple workers retry independently. Eventually the integration gets throttled more aggressively, incurs avoidable overage under its commercial terms, or loses access while engineers investigate.
The opening sync job violated the contract even though its underlying task was legitimate. The problem wasn't that the team fetched data. The problem was that a configuration change made the client behave as though shared capacity were unlimited.
For a B2B data API, professional hygiene means keeping concurrency below the documented allowance, measuring actual throughput, and separating interactive requests from bulk jobs. It also means designing for the provider's response semantics rather than assuming every endpoint has the same cost or retry behavior.
Keep this mental model: rate limits are the price of admission to a shared system. They protect fairness, make capacity more predictable, and give both sides a common language for traffic. Reading the policy carefully isn't an optional optimization. It's part of building a dependable integration.
Fetchin offers a real-time B2B data API that turns professional profile and company URLs into structured JSON, with synchronous responses by default and asynchronous delivery for higher-latency workflows. Visit Fetchin to review its API capabilities and design your worker concurrency, retries, and usage tracking around a documented data extraction workflow.



