Skip to main content
Back to blog

Rate limiting and throttling: definitions for API builders

Definitions of rate limiting and throttling for API builders: what each mechanism controls, how 429 responses and Retry-After headers work, and how to design retries that keep messaging deliverable.

Orbit Editorial Team

Rate limiting and throttling both cap how fast your application can call a messaging API, and confusing the two leads to retry storms that damage deliverability instead of protecting it. Rate limiting is a published quota enforced with rejections; throttling is traffic shaping that delays rather than refuses. This post defines each term with concrete request-flow examples, explains how limits are communicated over HTTP, walks the per-channel ceilings that matter in CPaaS, and lays out the tenant-side strategies that keep traffic compliant. If you want the operational variant with full per-endpoint budgets and a worked queue-drain, read /blog/rate-limiting-vs-throttling-cpaas-apis after this one.

What rate limiting means

Rate limiting is a published, static ceiling. For a given API key, account, or sender, the provider states a fixed allowance, such as requests per second, messages per minute, or concurrent calls. The limit is documented and predictable: you can architect around it before you write the first line of integration code.

In communications APIs the ceiling usually maps to a business concept. SMS limits tend to be expressed as messages per second or per minute per sender. Voice limits tend to be expressed as outbound calls per second or concurrent calls per account. Email limits are often per sending identity. The shape differs, but the property is the same: the allowance is fixed and knowable in advance.

A concrete request-flow example: you issue a burst of 2,000 SMS sends against a sender whose published ceiling is 100 messages per second. A rate limiter that only rejects hands you roughly 1,900 failed requests and forces you to build the requeue yourself. On Orbit, sender-velocity limits are throttles rather than hard rejectors: the excess 1,900 sends are spread out around your organization's configured limit, so a burst becomes a paced delivery stream instead of a pile of failures. The full gate-by-gate description is in the rate limits guide.

What throttling means

Throttling is dynamic reduction of traffic. When a request exceeds the allowance, the provider does not necessarily reject it outright. It queues it, slows the response, or paces delivery against a constraint. Carriers also throttle downstream of the CPaaS layer: US 10DLC throughput tiers cap messages per second per brand and route regardless of what the API itself would allow, and a newly registered US/CA 10DLC number carries a daily send ceiling that ramps up as it builds delivery history rather than a flat reject-all gate.

That distinction matters operationally. A rejection-style response such as a 429 is information. A client that reads the hint and backs off behaves very differently from a client that retries in a tight loop, which converts a small overage into a delivery incident. Throttling is the mechanism that lets a platform absorb that burst gracefully instead of feeding it back to you as errors.

How limits are communicated

The contract over HTTP has two pieces. First, the standing state of the limit travels on every response as headers: X-RateLimit-Limit (the maximum in the current window), X-RateLimit-Remaining (what is still available), and X-RateLimit-Reset (the Unix timestamp when the window resets). Second, when a rejection-style limit actually fires, the 429 response carries a Retry-After header and a retry_after field in the error body, both naming seconds, so header-readers and body-readers agree.

On Orbit these headers ship on every API response, and the 429 body's error code names which limiter family fired, because the right response differs by family. A throughput or request-cap code means wait for retry_after and spread the traffic. A frequency-cap code — a rule your own organization configured — means skip this recipient this window. A per-recipient cooldown means fix the loop, do not retry that recipient. Reading the code before deciding to retry is the entire trick. The taxonomy that maps each family to its codes lives in the rate-limit and cooldown taxonomy, and the same headers surface in the API playground as a first-class callout.

Per-channel considerations

The ceiling you plan around depends on the channel:

  • SMS: per-number or per-service velocity in messages per second, plus downstream carrier gates. NUMBER_MPS_EXCEEDED fires when you exceed a velocity hint and clears in about a second; a warming number refuses with DAILY_CAP_EXCEEDED or WARMING_QUOTA_EXCEEDED with a reset at midnight UTC. The number warming caps page walks the ramp gates.
  • WhatsApp: pacing sits on the template or message-service layer rather than the sender number, with a nearly identical MESSAGING_SERVICE_MPS_EXCEEDED-style code for spreading sends.
  • Voice: the relevant ceiling is outbound calls-per-second scoped per account rather than a free-running dial loop. A large campaign stays healthy by capping new-call creation to the published CPS and pacing the rest, not by opening more parallel workers.
  • API endpoints: every endpoint's per-minute budget is published (sends, lookups, webhook registration, reads), and one global per-second request ceiling rejects the excess immediately with no burst queue. The full table is in the rate limits guide.

Tenant-owned strategies

The platform enforces ceilings; the strategies below are yours to implement, and they are what separate a stable integration from a retry storm:

  1. Bounded exponential backoff. Sleep on the server's retry_after hint first; if it is absent, fall back to a capped exponential backoff with jitter, and give up after a fixed attempt count so a stuck limiter cannot loop forever. Retry only when the error code says the window will clear.
  2. Idempotency keys on every send. Store one Idempotency-Key per job and send it on every attempt, so a retried send cannot double-send even if the first attempt actually landed. The idempotency and safe retries companion post walks that contract end to end.
  3. Client-side queueing. Drain a bounded queue slightly below the published ceiling (for a 100-per-minute budget, drain at ~90 per minute) instead of firing from many parallel workers. Watch X-RateLimit-Remaining trend toward zero and slow the drain before the first rejection arrives.
  4. Quiet-hours interplay. Compliance gates are tenant-configured pacing rules that run before the send is accepted. A region or channel blocked by a send window or quiet hours returns BLOCKED_BY_SEND_WINDOW or BLOCKED_BY_QUIET_HOURS, and those sends belong deferred to the next window, not paced harder through the throughput gates. The definition and the gating chain are in send gating and quiet hours.

Frequently asked questions

What is the difference between rate limiting and throttling?

Rate limiting is a published quota enforced with rejections: exceed the budget and you get a 429 with a retry_after hint. Throttling is traffic shaping that delays rather than refuses — queueing, spreading, or pacing because a constraint downstream of the API (carrier throughput, a warming ramp) cannot absorb the rate.

What HTTP machinery communicates a limit?

Every response carries X-RateLimit-Limit, X-RateLimit-Remaining, and X-RateLimit-Reset. A rejection-style limiter answers 429 with a Retry-After header and a matching retry_after field in the error body, and the error code names the limiter family so you know whether to retry, skip the recipient, or fix the loop.

Does a 429 always mean I must retry later?

No. Read the code first. Throughput codes like NUMBER_MPS_EXCEEDED clear in about a second. Warming codes like DAILY_CAP_EXCEEDED point at the next UTC midnight — retrying every second burns your queue without clearing anything. Frequency-cap and per-recipient cooldown codes should not be retried against the same recipient inside the window at all.

Why would my sends pace out even when I never see a 429?

Because Orbit's sender-velocity limits are throttles. When you exceed a velocity hint, the platform spreads the excess around your organization's configured limit instead of rejecting it, so a burst becomes a paced stream. NUMBER_MPS_EXCEEDED is a per-second hint-level signal, not a hard wall, as the rate limits guide explains.

Where do quiet hours fit?

They are a separate, earlier gate. A send blocked by a tenant-configured send window or quiet hours returns BLOCKED_BY_SEND_WINDOW or BLOCKED_BY_QUIET_HOURS, which is a defer signal, not a throughput signal. Keep your retry strategies for the throughput codes and let the gating rule defer everything that falls outside the allowed window.

The definitions resolve to one sentence: rate limiting is the published ceiling you plan around; throttling is the dynamic response that keeps a burst deliverable. Treat them as separate mechanisms and your traffic stays both compliant and deliverable — and for the fraud-side throttling terms that gate SMS sends, see /blog/sms-pumping-fraud-2026-news-explainer.

Rate limiting and throttling: definitions for API builders — Orbit by Devotel