The write limit is an extra ceiling, not a separate allowance: a write is
counted against the general per-minute budget as well. Ten creates in a minute
costs ten of your sixty requests, not ten of a private pool.It exists because writes spend money. A loop that has lost track of itself can
issue sixty catalog reads a minute harmlessly; sixty rental creations a minute is
a different kind of afternoon.
GET /me reports yours in rate_limit_per_min, where
null means the account default. Test keys get a lower limit than live ones.
If your workload genuinely needs more, ask help@gpuoutlet.ai.
The per-IP limit is a separate rail from the per-key one, so a stolen key cannot
be used to hammer the API from a single host — and so one noisy tenant behind a
shared NAT does not get to spend everyone’s budget.
Headers on every response
RateLimit-Reset is seconds until the window resets, not a timestamp.
On a 429 you also get:
Treat RateLimit-Remaining as advisory
The honest model is: use the headers to pace yourself, and use 429 to stop.
A client that only reads headers will occasionally overshoot; a client that only
handles 429 will work but waste round trips. Doing both is a few lines.
Backing off
- Honour
Retry-After. It is the server telling you exactly how long the window has left. Guessing produces either a wasted retry or a needless wait. - Add jitter. Twenty workers that all sleep exactly 12 seconds will all retry in the same millisecond and half will get 429 again. A random fraction of a second breaks the convoy.
- Cap the total. Retrying forever turns a transient limit into a hung job.
Daily quota
Separate from the per-minute limit, and it fails differently:rate_limited: alert, and stop the
loop, rather than sleeping in it.
Staying well under
Page with limit=200, not limit=10
Page with limit=200, not limit=10
The same 1,000 offers cost 5 requests instead of 100. The maximum page size is
200; there is no reason to leave it at the default when you are walking a whole
result set.
Cache reference data
Cache reference data
/gpu-models, /regions and /prices change on the order of days. Fetch them
once at startup, not once per user action.Poll provisioning rentals every 2–3 seconds, not every 200ms
Poll provisioning rentals every 2–3 seconds, not every 200ms
Provisioning takes tens of seconds. Polling five times a second spends 300
requests a minute — your entire budget — to learn the same thing a dozen requests
would have told you.Once a rental is
running, stop polling it altogether unless you have a reason.Filter server-side
Filter server-side
/offers?gpu_family=h100-80gb®ion=us-east-1&available=true costs one request.
Fetching the whole catalog and filtering in your process costs dozens and gives
you the same answer, slightly staler. Every filter is listed in
Browsing the catalog.One client, not one per thread
One client, not one per thread
The per-key limit is shared across every process using that key. Ten workers with
their own idea of “60 per minute” produce 600.