Caching & quotas¶
Amazon API quotas¶
Amazon throttles its product APIs per Associates account. Historically, new accounts
start around 1 request per second and 8,640 requests per day, and the quota then
grows with the revenue generated by your shipped items. Check the current rules in the
Creators API documentation: when
the quota is exceeded, Amazon rejects calls and AMW answers HTTP 503 with a
Retry-After header until Amazon accepts calls again.
Caching layers¶
AMW is designed so that most page views never reach Amazon:
flowchart LR
W["Widget<br/>in-memory cache<br/>(5 min, per page)"] --> B["Browser / CDN / proxy<br/>Cache-Control: max-age"]
B --> A["AMW"]
A --> R[("Redis<br/>Redis.expire")]
R -. miss .-> Z["Amazon Creators API"]
| Layer | Controlled by | Notes |
|---|---|---|
| Widget memory cache | fixed, 5 minutes | Avoids duplicate requests within a page session. |
| HTTP caches | Server.httpCache |
Found products and widget.js carry Cache-Control: public, max-age=<httpCache>; errors, rate-limit answers and /health carry no-store, so a transient failure is never replayed by a cache. |
| NGINX micro-cache / CDN | your proxy | See Reverse proxy. |
| Redis | Redis.enabled, Redis.expire, Redis.staleExpire |
Shared by all visitors; survives AMW restarts. Products are fresh for Redis.expire and kept Redis.staleExpire longer as a fallback. |
| Not-found cache | Redis.notFoundExpire |
Remembers products Amazon does not know (in Redis, or in memory without Redis). |
Amazon price freshness¶
The Amazon Associates Program requires the price and availability shown to visitors to be less than 24 hours old. AMW enforces it on the server side:
Redis.expireis capped at86400seconds (a larger value is lowered at startup, with a warning in the logs). The Docker default is 12 hours.- A cached product older than 24 hours is never served, not even as a fallback while Amazon is down: it is fetched again, or the Amazon error is returned.
- The
Cache-Control: max-ageof a product response ismin(Server.httpCache, 24 h - age of the product), so browsers and CDNs drop it before it turns 24 hours old.
Recommended production values: Redis.expire between a few hours and 24 hours, and an
httpCache of a few hours (it also applies to widget.js).
Protecting the quota¶
Server.rateLimitcaps/productcalls per client IP and per minute (default 120).- Requests are validated before any cache or Amazon lookup, so malformed calls cost nothing.
- Each lookup requests a single item and a minimal set of resources (image, title, brand, price).
- Concurrent requests for the same uncached product share a single Amazon call.
- Products Amazon does not know are remembered for
Redis.notFoundExpireseconds.
When Amazon fails¶
- If Amazon fails (error, timeout, throttling) and the cache still holds an expired copy
of the product (kept
Redis.staleExpireseconds afterRedis.expire) that is less than 24 hours old, AMW serves that copy with HTTP 200; itstimestamptells how old it is. - After
Amazon.breakerThresholdconsecutive failures the circuit breaker opens: AMW stops calling Amazon forAmazon.breakerCooldownseconds, serves stale copies when it has them and otherwise answers HTTP 503 with aRetry-Afterheader. A single trial call then decides whether Amazon is back.