Limits & semantics
Flarelink adds almost no limits of its own — your backend runs on Cloudflare, so it inherits Cloudflare's. The few behaviours worth knowing up front are below. Cloudflare's numbers change over time; always confirm against their docs for anything you're designing around.
Inherited Cloudflare limits
| Thing | Limit (verify on CF docs) | Notes |
|---|---|---|
| D1 database size | up to ~10 GB per database | Per-database, not per-account. Plan a sharding/archival strategy well before you approach it. |
| D1 query result | bounded response size | Paginate large reads with .limit() / .offset(); don't SELECT * a huge table in one go. |
| Workers CPU time | ~10 ms (free) / much higher (paid) | Your auth Worker is light, but heavy per-request work (e.g. high-iteration password hashing) needs the paid plan — see hashing. |
| R2 single-PUT object | up to ~5 GB (single request) | Larger files need multipart upload (not yet wrapped in the SDK). No egress fees on R2. |
| KV value size | up to ~25 MB per value | Sessions are tiny; not a concern in practice. |
Authoritative source: Cloudflare's D1, Workers, R2, and KV limits pages.
KV eventual consistency & sign-out
Sessions live in KV (see Architecture). KV is eventually consistent across Cloudflare's edge — a write (or delete) propagates globally over a short window rather than instantly everywhere.
The practical implication: when a user signs out, the session is deleted from KV, but a request hitting a far edge that hasn't seen the delete yet could still validate that session for a brief period (typically up to a minute). For the vast majority of apps this is a non-issue — but if you're building something where instant global revocation matters (e.g. killing a session after a security event), don't assume sign-out is synchronous everywhere. The same window applies to brand-new sessions just after sign-in.
Presigned URL expiry
expiresInoncreateSignedUploadUrl/createSignedDownloadUrlis clamped to[60, 3600]seconds. The default is 300s. Values outside the range are clamped, not rejected.- Mint the URL right before you use it. A download URL embedded in a long-lived page will 403 once it expires — re-mint on demand from your server.
- Rotating R2 credentials invalidates in-flight presigned URLs signed with the old keys — see Rotating R2 credentials.
Storage list pagination
storage.from(bucket).list({ prefix }) returns at most 1000 objects per call (R2's ListObjectsV2 page size). When there's more, the response carries a nextCursor — pass it back in to fetch the next page:
The database builder has no implicit row cap, but bounded D1 response sizes mean you should always paginate large reads with .limit() + .offset() rather than pulling an entire table at once.