Rate limits & caching
How to read the delivery API efficiently — page sizes, ISR and CDN caching, revalidation webhooks, and backoff.
The delivery API is designed to be read constantly by production front-ends, so the practical question is less "how hard can I hit it" and more "how little do I need to". This page covers the built-in limits, the caching patterns we recommend, and how to keep content fresh without polling.
Request limits
- Page size: list endpoints cap
limitat 100 entries per request. Ask for more and you get 100; page withoffset(or cursor parameters where available) to read a full collection. - Self-hosted instances: there is no artificial request-per-minute meter in the product — throughput is bounded by your own infrastructure (CPU, Postgres, network). Put a CDN or cache in front rather than sizing the box for peak reads.
- Managed/hosted setups: the host's platform limits apply (see your plan). The client patterns below keep you comfortably inside any of them.
The @flowcms/client SDK paginates for you and reuses connections. If you are
hand-rolling fetch(), reuse one base URL + token and page in a loop rather
than firing one request per entry.
Cache at the edge, not in your code
Published content is public and cache-friendly. The three patterns, in order of preference:
- Static generation / ISR — build pages from the API and revalidate on a timer (60–300 s works for most sites). This is how flowcms.co itself reads its help center and blog.
- CDN in front of the API — for client-side reads, cache
GET /api/public/:typeresponses at your CDN keyed by the full query string. Published content only changes on publish, so even a 60 s TTL removes almost all origin traffic. - HTTP caching — responses are deterministic for a given query; honour
Cache-Controland add your ownstale-while-revalidateat the edge for smooth refreshes.
Refresh on publish, don't poll
Instead of short cache TTLs everywhere, let the CMS tell you when something changed:
- Configure a webhook on
content.published/content.updated(see Webhooks) pointing at your site's revalidate endpoint. - The endpoint purges just the affected surface (a tag, a path, a cache key) — content appears seconds after publish with no rebuild and no polling.
This is the exact pattern this site uses: a Flow CMS webhook hits
/api/revalidate with a shared secret, which purges the help, blog or
pricing cache tags on demand.
Backoff and retries
Treat the API like any HTTP dependency:
- Retry idempotent GETs on
429and5xxwith exponential backoff and jitter (e.g. 0.5 s → 1 s → 2 s, three attempts). - Respect
Retry-Afterwhen present. - Fail soft: keep rendering the last cached copy if a refresh fails. Every section of this site degrades to its last snapshot when the CMS is unreachable — that is the behaviour to copy.
Draft/preview reads (with a preview token) are personal and uncacheable — keep them out of your CDN and off hot paths. Only published, public reads belong in the cache.