Get started / Overview
UsageRail docs
UsageRail adds API keys, rate limits, quotas and usage metering to an API you already run. The SDK checks each request inside your own process and reports usage per customer in the background, so your requests never pass through us. Most requests are decided from copies the SDK keeps in memory. For a key it hasn't seen yet, or a customer whose quota lease has run out, the SDK asks UsageRail first. A lease is the slice of a customer's quota that one server may hand out on its own.
import express from "express";
import { usageRail } from "@usagerail/node/express";
const app = express();
// Checks the API key, rate limit and quota, then counts the request
app.use(usageRail({
appKey: process.env.USAGERAIL_APP_KEY,
auth: "api-key",
}));New here? The quickstart takes you from an empty app to a counted request in a few minutes.
How the parts fit together
The SDK, in your API. It keeps a copy of your customers' keys and limits in memory, so most requests are checked without a network call. Checking a key created since the last sync waits up to 300 ms for UsageRail, and so does getting a quota lease for a customer who has none; one request can need both. It counts each request by customer, endpoint and outcome, and sends the counts to UsageRail every 60 seconds.
UsageRail. It stores your customers, plans and keys. Every running copy of the SDK syncs with it every 15 seconds, which is how a revoked key or a new limit reaches all your servers. It also hands out quota leases, which keep a quota shared by many servers within its limit; quotas lists the cases where usage can still go over.
Your developer portal. A portal under your name where your customers sign in, create and rotate their own keys, and see their usage. Its default address is {your slug}.usagerail.app, and you set it up in the console, where you also manage the same customers.
Billing. Customers subscribe to your paid plans through your own Stripe account, which you connect with a restricted key. At the end of each month, their usage beyond the plan's included units goes on their Stripe invoice. On a prepaid plan, customers buy your credit packs instead and use them up as they go.
Pick an integration
| Your stack | Install | Guide |
|---|---|---|
| Express | npm install @usagerail/node | Express middleware |
| Hono on Node.js | npm install @usagerail/node | Hono middleware |
| Fastify | npm install @usagerail/node | Fastify plugin |
| Next.js route handlers, on Vercel or elsewhere | npm install @usagerail/node | Next.js |
| Hono on Cloudflare Workers | npm install @usagerail/node hono | Cloudflare Workers |
| FastAPI or Starlette | pip install usagerail | FastAPI |
| Flask | pip install usagerail | Flask extension |
| Django | pip install usagerail | Django middleware |
| Go, PHP, Ruby, Java, .NET and others | Nothing to install | HTTP check |
Two ways to know who is calling
Keys from UsageRail (auth: "api-key"). You create keys in the console or through the server API, and your customers create their own in the portal. The SDK reads the key from the Authorization: Bearer header or from x-api-key, checks it, and knows which customer it belongs to. See API keys.
Your own authentication (auth: "custom"). If your API already has logins or keys of its own, give the SDK a consumer function that returns your ID for the caller. UsageRail creates the customer the first time it sees that ID. By default the ID is hashed with a secret of your app before it leaves your server.
Either way, rate limits and quotas work the same.
What you need
- An app in the console. Each app has its own customers, keys and settings, and test and live are separate apps.
- The app key from the app's page. It starts with
urk_test_orurk_live_, and the SDK uses it to sync and to report usage. Keep it on your server, in an environment variable such asUSAGERAIL_APP_KEY, and never send it to a browser or a mobile app.
How much time the SDK adds
On October 28, 2026 we timed the Node.js SDK's check at the start of a request and its accounting at the end, with keys and limits already synced and no network calls: 200,000 requests per case, on a server with 2 vCPUs (Intel Xeon Platinum 8255C) and Node.js 22.
| Case | p50 | p99 | p99.9 |
|---|---|---|---|
| Key from UsageRail, plan that bills overage, rate limited | 5.2 µs | 14.8 µs | 448 µs |
| Key from UsageRail, stop-at-limit quota | 5.7 µs | 19.5 µs | 446 µs |
| Your own authentication, hashed ID | 2.8 µs | 5.0 µs | 131 µs |
Your framework's own overhead isn't included. A request that has to ask UsageRail waits up to 300 ms for each thing it asks about, a key created since the last sync or a quota lease, and one request can need both.
When UsageRail is unreachable
Your API keeps serving. Keys the SDK already knows keep working from its local copy for up to 24 hours. Usage is held in memory and retried for up to 10 minutes; counts older than that are dropped, never billed, and reported as missing once UsageRail is reachable again. Two cases need a decision, and you make it in the app's settings:
- A key the SDK hasn't seen yet, such as one created a few seconds ago. By default the SDK refuses it with a 503, because it can't confirm the key is real. See API keys.
- A customer whose quota can't be checked. By default the SDK lets the request through and counts it, so the customer can go over the quota while UsageRail is unreachable. See quotas.