Skip to content

Rate limits

Rate limits are not enforced yet

Statable does not apply per-account rate limits today. You can call the Stats API as fast as your client can issue requests. The limits below describe what we plan to ship, not what's live. This page exists so you can build with the future in mind and avoid retro-fits later.


Today

No 429s. No X-RateLimit-* headers. The only effective ceiling is underlying ClickHouse query latency and your own client throughput. Server-side caching means hot endpoints (top-stats, graphs) round-trip in tens of milliseconds, but every uncached request still hits the database.

One exception worth knowing: results in ClickHouse refresh on a flush cycle of roughly 10 seconds. Polling faster than that returns the same numbers. You're paying for round-trips that can't show you new data.


What's coming

Per-plan request budgets, with response headers so your client can self-throttle:

PlanIndicative limit
Free / Hobby~60 requests/minute
Starter~300 requests/minute
Pro~600 requests/minute
EnterpriseCustom

Exact numbers will be finalized before launch. Treat this as direction-of-travel, not a contract.

Headers (planned)

When limits ship, every response will include:

X-RateLimit-Limit: 600
X-RateLimit-Remaining: 542
X-RateLimit-Reset: 1730203200
  • X-RateLimit-Limit: total budget for the current window.
  • X-RateLimit-Remaining: calls left in the window.
  • X-RateLimit-Reset: Unix timestamp when the window rolls over.

A 429 Too Many Requests response will also carry:

Retry-After: 17

Wait that many seconds before retrying. The error envelope will use code: "rate_limit_exceeded" (see Errors).


Best practices for now

Even without enforcement, polite clients future-proof against the day limits land:

  • Cache aggressively. Query results change at ClickHouse flush cadence (~10 s). Caching for 10–30 seconds in your application layer eliminates duplicate round-trips with no observable lag.
  • Batch where the API allows. A single /site/top-stats call returns five metrics. Don't issue five calls.
  • Pick the right period. Pulling period=12m once an hour beats pulling period=24h every minute and reconstructing the month yourself.
  • Use interval deliberately. Don't ask for interval=hour over period=365d if you only need monthly buckets. Let auto-resolution pick day/week/month for long ranges.
  • Stop polling closed periods. Yesterday's numbers don't change after a few minutes. Once a period is settled, cache and move on.
  • Avoid bursting on cold start. If you hydrate a dashboard with 20 calls at once, stagger them by a few hundred ms so a future burst limit doesn't kick you in the face.

Real-time endpoint exception

/site/current-visitors is a special case. It's the one endpoint whose numbers genuinely change every few seconds. Even there, don't poll faster than once every 5 seconds. The underlying counter has its own short TTL. Calling it 10 times per second returns the same number 9 times and just burns request budget you'll eventually have to pay for.

// Bad, burns calls, returns identical numbers
setInterval(refresh, 500);

// Good, matches the data's actual update cadence
setInterval(refresh, 5000);

When limits ship

This page will be updated with:

  • Final per-plan numbers.
  • Window length (per minute / per hour) and burst behavior.
  • A code sample for backing off cleanly using X-RateLimit-Remaining and Retry-After.

Want a heads-up before enforcement turns on for your account? Ping [email protected]. We'll give existing customers warning, not a surprise 429.


Ready to take control of your web analytics? Try Statable free for 30 days — no credit card required, full feature access, GDPR-compliant by default. Start your free trial or view a live demo.