AeroModel
Documentation
DDoS and rate limiting
The API runs on Cloudflare Workers, which provides built-in layer 3/4/7 DDoS protection.
Automatic protection
Cloudflare automatically blocks:
- SYN, ACK, UDP floods (layer 3/4).
- Volumetric HTTP attacks.
- Bots known to the Cloudflare database.
- Vulnerability scans.
No action on your part — it's bundled with the Workers plan.
Application rate limiting
The API does not (yet) have an explicit per-key rate limit. But Cloudflare applies global limits (burst control) preventing a single caller from saturating one datacenter.
If you need strict guarantees (X req/sec), contact the admin to enable a Cloudflare WAF rate limit rule on your key.
Client-side best practices
1. Cache your results
Images are cacheable for 24h browser-side (cache-control: public, max-age=86400). Reuse the HTTP cache rather than re-firing the same URLs.
2. Use a CDN
If you proxy via your backend, put a CDN in front. The same URL repeated 1M times should hit the API at most once per datacenter.
3. Prefer slugs
Slugs are stable → cache hit. Plain-text names can produce several distinct URLs for the same image (Air France vs air france vs air-france depending on your normalization).
4. Avoid polling
Images don't change multiple times per second. If you build a dashboard, refresh at most every hour.
Quotas
The current Cloudflare Workers Paid plan includes:
- 10M requests/month included.
- 30s CPU/req max (largely sufficient for compositions).
- R2 reads free up to a certain volume (see Cloudflare R2 pricing).
If you expect more than 10M req/month, ask the admin to prepare a scaling plan.
What if you get blocked (429 / 1015)
| Code | Meaning | Action |
|---|---|---|
429 Too Many Requests | You exceeded the Cloudflare rate limit. | Wait Retry-After seconds. |
1015 (Cloudflare HTML) | IP block by WAF. | Contact the admin. |
503 Service Unavailable | Worker down or in maintenance. | Retry with exponential backoff. |
Client-side backoff
async function fetchWithBackoff(url, init, retries = 3) {
for (let i = 0; i < retries; i++) {
const r = await fetch(url, init);
if (r.status !== 429 && r.status !== 503) return r;
const wait = Number(r.headers.get("retry-after")) || 2 ** i;
await new Promise((rs) => setTimeout(rs, wait * 1000));
}
throw new Error("max retries reached");
}