Rate limits
Handle request-rate and concurrency limits without duplicating operations.
Ecomiq does not apply one quota to every operation. The limit depends on the API and the policy attached to the endpoint.
What can produce 429
| Limit type | What it controls |
|---|---|
| Global | Overall request volume from a client or address. |
| Per endpoint | Sensitive flows such as authentication, writes, analytics, or callbacks. |
| Concurrency | How many expensive operations may run at the same time. |
A 429 Too Many Requests response may come from any of these layers. Do not
infer a universal number from one endpoint or environment.
When the response includes Retry-After, use it as the minimum wait. Otherwise,
use exponential backoff with random jitter.
Safe retry
async function retryAfter429(
request: () => Promise<Response>,
canReplay: boolean,
) {
for (let attempt = 0; attempt < 4; attempt += 1) {
const response = await request();
if (response.status !== 429 || !canReplay) return response;
const retryAfter = response.headers.get("retry-after");
const fallback = Math.min(30_000, 500 * 2 ** attempt);
let delay = fallback + Math.random() * 250;
if (retryAfter !== null) {
const seconds = Number(retryAfter);
if (Number.isFinite(seconds)) {
delay = seconds * 1000;
}
}
await new Promise((resolve) => setTimeout(resolve, delay));
}
throw new Error("Rate limit persisted after 4 attempts");
}canReplay must come from the operation contract. Enable it only for a read, an
idempotent operation, or a write protected by an idempotency key.
Also cap the total number of attempts. If several workers share credentials, coordinate their wait so they do not send the same burst again.
Imports
An accepted import runs asynchronously. Keep its identifier and query the status endpoint; do not upload the file again to check progress.
Submitting or validating an import can return 429, including from a
concurrency limit. Wait and retry only after confirming that the operation was
not accepted.
Reduce pressure
- Use the largest page size supported by that endpoint.
- Limit client concurrency; a local queue is often enough.
- Cache data that changes infrequently, such as categories or zones.
- Use webhooks when the event you need exists.
- Avoid fixed-interval polling; increase the interval when nothing changes.
Published defaults and headers may vary across APIs. Build the client around the actual response, not an assumed shared quota.