Announcing rate limit and quota changes: when the breaking change is a number

There is a class of API change that no tooling can catch. The OpenAPI diff is clean: no endpoint moved, no field changed type, no version was bumped. The SDKs don’t warn. Staging — where nobody generates production volume — passes every test. And yet integrations that ran flawlessly for two years are about to start failing, because you changed a number: requests per minute, rows per export, calls per month, webhooks per day. Rate limits and quotas are as much a part of your contract as any schema — consumers tuned their retry loops, batch sizes, polling intervals, and sometimes their entire business model against the old values — but they live in prose and headers, not in anything a diff tool reads. When the contract is a number, the announcement is the only interface you have.

This guide covers the discipline for changing limits: why these changes fail crueler than ordinary breakage, the taxonomy (cuts, new limits, window changes, enforcement flips — each needs different handling), the worked-example rule, in-band signals, timelines sized to re-architecture, and a full entry template. It’s the numeric sibling of the API changelog and shares a spine with announcing pricing changes — not least because so many limit changes secretly are pricing changes.

Why limit changes fail worse than ordinary breakage

Two properties make a limit change nastier than a removed endpoint:

  • It binds at peak. A removed endpoint fails the first call after the change — loudly, immediately, in everyone’s staging environment. A lowered rate limit fails only under load, which means the failure arrives during your consumer’s busiest hour: the retailer’s holiday spike, the payroll run, the product launch. The change lands at the exact moment the people affected can least afford to handle it — by construction, not by bad luck.
  • Nothing announces it in the code path. Deprecated endpoints can carry warning headers for months. A quota cut has no natural in-band warning unless you build one — the first signal most integrations get is the 429 itself. Whatever notice exists is whatever you deliberately created.

Together these mean the honest default is to treat every tightening of a limit as a breaking change, with the announcement discipline that implies — even though your version number won’t move.

A taxonomy of limit changes

  • Raising a limit. The happy case — and still worth a changelog entry. Consumers built batching and backoff machinery around the old ceiling; telling them it moved lets them simplify. It also teaches readers that limits are documented here, which is exactly where you want their eyes before the day you announce a cut.
  • Lowering a limit. A breaking change wearing a configuration change’s clothes. Full treatment below.
  • Adding a limit where none existed. The harshest case, because unlimited was the documented behavior. Integrations were architected on it — the nightly full-sync exists because nothing said it couldn’t. Announce it like the removal of a feature, because that’s what it is.
  • Changing the window or scope. “600 per hour” and “10 per minute” are the same arithmetic and completely different contracts — one permits bursts, the other throttles them. Per-key to per-organization changes the math for every customer running parallel workers. Fixed-window to sliding-window changes what a correctly-tuned retry loop does at the boundary. Announce semantic changes as loudly as numeric cuts, and spell out the burst behavior, because “the number didn’t change” is precisely what makes these invisible.
  • Enforcing a limit that was documented but never enforced. Hyrum’s Law has a quota corollary: the real limit is the enforced one. If the docs said 100 per minute and production allowed 400, consumers depend on 400 — whatever the docs say. Turning enforcement on is a behavior change for them and deserves the same announcement, grace period, and dry-run treatment as a cut. “It was always documented” explains your position; it doesn’t un-break anyone.

Tell each reader whether they’re affected

The reader’s only question is am I over the new line, and by how much? Answer it in three layers:

  • Worked examples in the announcement. The same worked-example rule that governs fee changes: never percentages alone, never abstractions. “If your key makes fewer than 5,000 calls per day, nothing changes. A key polling every 10 seconds around the clock makes about 8,600 — over the new line; switching to webhooks or 30-second polling brings it under.” Name the usage patterns that cross the threshold, because every reader recognizes their own architecture in a pattern faster than they can do the arithmetic.
  • Per-account numbers where accounts can see them. The dashboard knows each key’s current usage; show it next to the new limit. If a small fraction of accounts are affected, email exactly those accounts with their own numbers — “your peak day last month was 2.4× the new quota” turns an abstract policy into a scoped task. And say the honest version in public: “about 3% of active keys exceed the new limit” is information; “most users won’t be affected” is the same claim dressed as reassurance, and readers can tell.
  • The changelog as the public record. Targeted emails reach the affected; the changelog entry is what next year’s integrator finds, what the support thread links, and what proves the change was announced and when. Segment the delivery, never the record.

Announce in-band, not just in prose

Deprecations get RFC 8594 headers; give limit changes the same in-band courtesy:

  • Rate limit headers, before and after. If responses carry current-limit headers (RateLimit-Limit, X-RateLimit-Remaining, or kin), automation can see the ceiling move — provided you announce that the values will change on a date, so alert thresholds get updated rather than tripped.
  • A dry-run period. Enforce the new limit in log-only mode first: requests that would have been throttled succeed but get flagged — a response header, a dashboard warning, an email digest of would-be-429s. This converts “we announced it, they didn’t read it” into a tripwire that fires in the consumer’s own monitoring, weeks before anything breaks.
  • 429s that explain themselves. During the transition, the throttled response should carry Retry-After and a link to the announcement entry. An error that arrives at 2 a.m. with a permalink to what changed, when it was announced, and what to do is the difference between an incident and an errand.

Timelines: treat a cut like a removal

  • Size the window to the re-architecture, not the config change. For you, the change is editing a number. For the consumer over the line, it may mean building a caching layer, moving from polling to webhooks, or re-batching a pipeline — engineering projects with their own backlogs. A quota cut with two weeks’ notice is a removal with two weeks’ notice; your deprecation policy’s windows are the right starting point, and the announce-3x cadence (announcement, reminder, change-day confirmation) applies unchanged.
  • Split effective date from enforcement date. “New limits take effect March 1; hard enforcement begins April 1; between the two you’ll see warnings, not errors” gives the dry-run period a public schedule and every reader a deadline they can plan against.
  • Never retroactive, never mid-cycle. Quota already granted this billing period is spent against the old number; a monthly cap that shrinks mid-month punishes consumers for usage you already approved. Cuts take effect at a cycle boundary — and not during your customers’ peak season, a rule fee schedules and quotas share.

The entry itself

Old value, new value, scope, dates, what to do — exact numbers, in a form a stranger can act on:

Changed — API rate limits for Free and Starter plans (effective Apr 1)

What changes: requests per minute drops 300 → 120 on Free and
600 → 300 on Starter. Applies per API key, across all v2 endpoints.
Growth and Enterprise limits are unchanged. Burst behavior is unchanged
(sliding 60s window).

Are you affected? About 4% of active keys exceeded the new limits last
month. If your key stays under 120 requests/min at peak, nothing changes.
Affected accounts: your dashboard now shows your 30-day peak next to the
new limit, and we’ve emailed every account over the line.

Dates: warnings begin Mar 1 (requests over the new limit succeed and
return an X-RateLimit-Warning header). Hard enforcement begins Apr 1,
at the start of the billing cycle.

What to do: use the bulk endpoints (up to 100 records/call), subscribe
to webhooks instead of polling, or raise your limit on the Growth plan.
Migration notes: <url>

Why: sustained growth in automated traffic; this keeps p99 latency flat
without raising prices for the 96% of keys under the line.

Two notes on that last line. Give the real reason — capacity, abuse, cost — in one sentence; readers extend enormous credit for “this was costing us more than you pay us” and none for “to improve platform reliability.” And if the honest reason is revenue — the limit exists to move heavy users to a paid tier — then this is a pricing change and owes the pricing-change disciplines too: grandfathering decisions stated explicitly, and the same entry in both records.

Six anti-patterns

  • The silent enforcement flip. Turning on enforcement of a long-ignored documented limit with no announcement, then pointing at the docs. Contractually clean, reputationally identical to an unannounced cut.
  • The docs-only edit. Changing the number on the limits page with no dated entry anywhere. Silent edits to load-bearing docs are exactly the case where a changelog entry is mandatory — the before/after and the date are the announcement.
  • Percentages without absolutes. “Limits reduced by up to 60%” forces every reader to reverse-engineer their own number. State old and new values per plan, per endpoint class.
  • “Limits may vary” as policy. Refusing to document limits so you never have to announce changes. Consumers discover the real values empirically and build on them anyway — you have the same Hyrum’s-Law exposure with none of the trust.
  • Treating overage as abuse. Suspending keys or mass-blocking traffic patterns you permitted for years, with an announcement written like a fraud notice. If yesterday’s architecture was allowed, its owners are customers with a migration ahead of them, not attackers.
  • The buried motive. Announcing a monetization-driven cut as a neutral technical adjustment. Readers compare the new free-tier ceiling to your paid tiers within minutes; when the upsell is discovered rather than stated, you pay for the cut twice.

Running it on Wakelog

The mechanics above map directly onto Wakelog: post the announcement as a dated entry tagged breaking so it stands out in the feed and survives as the permanent record; schedule the reminder and the change-day confirmation with publish_at so the announce-3x cadence ships the day legal and capacity planning sign off; and let the RSS and JSON feeds serve as the tripwire for every consumer — and every team that monitors vendor changelogs — whose monitoring reads feeds instead of inboxes. The permalink is what your 429 response body and dashboard warning link to. The honest boundary: Wakelog doesn’t know your customers’ usage, so per-account numbers and affected-key emails stay in your product — the changelog is the public, citable half of the announcement.

Start your changelog — free   Next: API changelogs →

Related guides

Last updated 2026-08-02 · All guides