Developers

Rate limit deep-dive

DevelopersRate limit deep-dive

A deeper look at how rate limiting works in BookFlow, why it's designed the way it is, and how to operate within (or around) it for high-volume integrations.

Why we rate limit

  • D1 protection — every D1 query costs us money. Rate limiting prevents 429s bad clients before they burn our budget.
  • KV protection — same idea for KV, the rate-limit counter store.
  • Abuse prevention — credential stuffing, scraping, and accidental client bugs (e.g. a runaway loop calling /bookings every second).
  • Fairness — one tenant can't starve another by hammering the API.

Implementation

The rateLimit middleware reads cf-connecting-ip and increments a counter in KV under the key {prefix}:{ip}. The counter expires with the window. When the counter would exceed the limit, the request is rejected with HTTP 429 before the handler runs.

Per-tier limits

Not implemented
The rate-limit middleware today is a single per-IP, per-route-group counter. There is no plan-tier multiplier (Free / Pro / Enterprise) wired into the limiter. The numbers in this table are aspirational and not enforced by the API yet.

Backoff strategy (recommended)

  1. On 429, read the Retry-After header.
  2. Wait that many seconds.
  3. Retry once. If still 429, double the wait (exponential backoff).
  4. Cap the wait at 5 minutes.
  5. After 5 consecutive 429s, give up and contact support.

Detection (recommended)

On every 429 response, the Worker sets a Retry-After header. There is no X-RateLimit-Limit, X-RateLimit-Remaining, or X-RateLimit-Reset header set by the current middleware. Plan your retry around the single Retry-After value.

Batching

If you need to fetch many records, use the limit parameter (up to 200 per request) instead of making many small requests. Saves you 10x the rate-limit budget.

Caching

Public tenant data (GET /api/public/:slug) changes rarely. Cache it on your side for 5 minutes. You'll avoid unnecessary rate-limit pressure.

Webhooks instead of polling

Instead of polling GET /api/bookings every minute, subscribe to webhooks (booking.created, booking.cancelled, etc.). Saves you from hitting rate limits and gives you faster updates.

How to request a rate limit increase

For Pro tier, the defaults are usually enough. If you have a specific high-volume use case, contact hello@netwit.ca with:

  • The endpoint(s) you need higher limits on
  • Your expected request volume per minute
  • What you're building (so we can suggest the right approach)
  • Whether you can use webhooks or caching to reduce the load

What happens at the limit

You get a 429 with the body { "error": "rate_limited" } and the headers described above. Your request didn't run — no side effects, no partial state. Just wait and retry.

Need a human?

Email hello@netwit.ca or call +1-604-206-8169. NetWit responds in 1 business day.