Decision
Two limiter strategies behind one interface: a token bucket when the requests-per-minute figure is published, and an adaptive controller when it is not.
Context
Internal gateways frequently publish no quota, and the real limit changes without notice.
Alternatives, and why not
- Require every consumer to configure a rateThey will guess. Guessing low wastes hours on a batch; guessing high produces a throttling storm and a support conversation.
- Retry with exponential backoff and no pacingIt converges on the limit by repeatedly exceeding it, which is the behaviour that gets a service throttled at the account level.
Rationale
Start conservative at six seconds between requests, reduce the delay by ten percent after three consecutive successes, multiply it by 1.8 with a ten-second cooldown on a throttle, and clamp to a configured range. Additive increase, multiplicative decrease: the same control loop that governs TCP, applied to an API quota.
What it cost
The first minute of a batch is slower than a correctly configured constant rate would be. The trade buys never needing that configuration to be correct.
Outcome
Batches self-tune to whatever the provider is currently allowing, including when that changes mid-run.