UpstashRedisRateLimiter is the Rate Limit component’s serverless backend. It builds on @upstash/ratelimit and Upstash Redis over HTTP REST to enforce distributed limits across instances and edge functions — no shared in-memory state. It implements the framework’s IRateLimiter interface, so the calling code is identical to any other backend.
Why Upstash
- Distributed by default. Counters live in Upstash Redis, so the same limit holds across every instance and region.
- Serverless-friendly. Talks to Upstash over HTTP REST, which works in edge functions and short-lived runtimes.
- Three algorithms. Fixed window, sliding window, or token bucket — chosen with a single option.
- Built-in analytics. Upstash rate-limit analytics are enabled by default for dashboard insight.
- Same
IRateLimiterinterface.check,isLimited,reset, andgetCount— identical to the other backends.
Installation
UpstashRedisRateLimiter ships with @ooneex/rate-limit and depends on the Upstash rate-limit and Redis clients.
Environment variables
| Variable | Required | Purpose |
|---|---|---|
RATE_LIMIT_UPSTASH_REDIS_URL | Yes | Upstash Redis REST URL. Missing throws RateLimitException (CONFIG_REQUIRED). |
RATE_LIMIT_UPSTASH_REDIS_TOKEN | Yes | Upstash Redis REST token. Missing throws RateLimitException (CONFIG_REQUIRED). |
url, token), which take precedence over the environment. They are validated when the limiter is constructed, so misconfiguration fails fast.
Options
UpstashRedisRateLimiter accepts an options object as its second constructor argument:
| Option | Type | Default | Purpose |
|---|---|---|---|
url | string | RATE_LIMIT_UPSTASH_REDIS_URL | Override the REST URL. |
token | string | RATE_LIMIT_UPSTASH_REDIS_TOKEN | Override the REST token. |
algorithm | UpstashAlgorithmType | sliding window, 120 / 60 s | The limiting algorithm and its parameters. |
prefix | string | "ratelimit" | Redis key prefix; falls back to namespace. |
namespace | string | "ratelimit" | Alias for prefix. |
analytics | boolean | true | Enable Upstash rate-limit analytics. |
Algorithms
Thealgorithm option is a tagged union — pick one and supply its parameters:
window and interval are Upstash Duration strings such as "60 s", "1 m", or "1 h". The default is a sliding window of 120 requests per 60 seconds.
How it works
check(key) calls the underlying limiter and normalizes the result into a RateLimitResultType:
| Field | Type | Purpose |
|---|---|---|
limited | boolean | Whether this request exceeded the limit. |
remaining | number | Requests left in the current window. |
total | number | The configured limit. |
resetAt | Date | When the window resets. |
| Method | Purpose |
|---|---|
check(key) | Consume one unit and return the full result. |
isLimited(key) | Convenience boolean — whether the key is over the limit. |
reset(key) | Reset the used tokens for a key; returns true on success. |
getCount(key) | Remaining requests for a key. |
Usage
Key the limiter by whatever identifies the caller — an IP, a user id, or an API key.Use in the app
In an@ooneex/app application, pass UpstashRedisRateLimiter to the rateLimiter slot of your App config. The framework registers it and exposes it as the "rateLimiter" container constant.
check() yourself. When a request is over the limit it short-circuits with a 429 Too Many Requests and sets the standard headers automatically:
rateLimiter slot instead. Set RATE_LIMIT_UPSTASH_REDIS_URL and RATE_LIMIT_UPSTASH_REDIS_TOKEN in your .env.yml (or environment).
Exceptions
UpstashRedisRateLimiter throws RateLimitException (HTTP 429) on misconfiguration or operation failures, carrying a machine-readable key.
| Key | When |
|---|---|
CONFIG_REQUIRED | The REST URL or token is missing from both options and the environment. |
RATE_LIMIT_CHECK_FAILED | A check() call against Upstash failed. |
RATE_LIMIT_RESET_FAILED | A reset() call failed. |
RATE_LIMIT_COUNT_FAILED | A getCount() call failed. |
Best practices
- Pick the algorithm for the job. Sliding window for smooth API limits, fixed window for simple per-minute caps, token bucket for burst-tolerant limits.
- Key by the right identity. Rate-limit by user id for authenticated routes and by IP for public ones; use a distinct
prefixper limiter. - Surface
resetAt. Return aRetry-Afterheader and429so clients back off correctly. - Keep credentials in the environment. Load the REST URL and token from
.env; never hard-code them. - Share one Upstash database safely. Give each limiter its own
prefix/namespaceso independent limits don’t collide.