Reference / Known limitations
Known limitations
What UsageRail doesn't do, or doesn't do yet, and the edge cases where counts or limits behave differently from what you might expect. If something here gets in your way, tell us: it shapes what we build next.
Not live yet
- Billing through Stripe. Paid plans, overage billing, checkout and invoices aren't live. Until they are, customers can only be on free plans, which can still have a quota and rate limits.
- Prepaid credits. Plans that use prepaid credits can be set up, but customers can't buy credits yet.
- The pricing table you'd embed on your own site.
- Serverless platforms. The Node SDK has a mode for platforms such as Vercel functions and Cloudflare Workers, where an instance can be frozen between requests. We'll document a platform once we've measured that it loses almost no counts there, and those measurements aren't finished. Until then, run the SDK on a long-running server, or use the HTTP check.
Counts that can be lost
- Hard kills. Counts are sent every 60 seconds. A process killed with
kill -9or by running out of memory loses the counts it hadn't sent, and they're never billed. A normal shutdown sends them first. - Long outages. While UsageRail can't be reached, the SDK keeps unsent counts in memory for up to 10 minutes and retries. Older counts are dropped and reported as missing once we're reachable again, so you can see the gap, but they're never billed.
- Clients that disconnect. With Express, Fastify and FastAPI, a request the client abandoned before the response started is recorded as aborted and isn't billed. Hono, Flask and Django don't notice when a client leaves early, so they count the request by its status.
Limits that bend
- Rate limits are per process unless you split them across servers, and a restarted process starts with full buckets. See rate limits.
- Quotas can be exceeded in a few specific cases, such as a request that uses more units than it reserved, or a crash that loses usage a server hadn't reported yet. Quotas lists them all, with how much each can add.
- New customers with your own authentication have no rate limit for up to about 15 seconds, until the next sync brings their plan. Their quota applies from the first request.
- While UsageRail can't be reached, quotas aren't enforced by default, so a customer can go over for as long as the outage lasts. You can choose to refuse those requests instead; see quotas.
Size limits per process
- Keys. Each process keeps up to 100,000 keys locally. Keys beyond that are checked with UsageRail on first use, which adds one round trip.
- Customers. Each process keeps the settings of up to 100,000 customers. Customers beyond that have no local rate limit; their quotas still apply. When an app is near that size and a full sync replaces customers who were deleted with new ones, the new ones can go without a local rate limit until the next full sync.
- Active customers. Each process keeps quota and rate limit state for the 40,000 customers it saw most recently. A customer who drops out starts fresh when they return, with one extra round trip on their next request.
- Routes. Each process records up to 500 different routes per minute. Past that, usage is grouped under
_other.
Frameworks
- WebSockets. The Express middleware and the Python SDK don't check or count WebSocket connections. Hono counts a successful handshake once, and so does Fastify with
@fastify/websocket. - Express sub-apps. Requests handled inside an app made with
express()and mounted withapp.use()are grouped by their concrete path, such as/tenants/42/files, not by a template. Useexpress.Router()where you want usage grouped by route. - Routes defined before the import. Express routers mounted before
@usagerail/node/expressis imported are grouped by concrete path too.
The HTTP check
- One extra round trip on every request.
- No refunds. An allowed check is counted at once, even if your request then fails. See counting.