Profiles·Public

@upstash/ratelimit

semver>=1.0.0postconditions11functions8last verified2026-06-24coverage score89%

Postconditions: what we check

  • limit · ratelimit-limit-no-try-catch
    error
    WhenNetwork failure to Redis OR invalid Upstash credentials — Redis HTTP call throws when the connection fails before the timeout logic resolves.
    ThrowsError (network failure or auth error from @upstash/redis HTTP client)
    Required handlingCaller MUST wrap ratelimit.limit() in try-catch. If Redis is unreachable, the underlying HTTP client throws. In most serverless API routes, this unhandled error crashes the entire request. Fail open (return true/allow) on Redis errors to avoid blocking all users when the rate limiter is unavailable.
    costmediumin prodimmediate exceptionusers seeservice unavailablevisibilityvisible
    Sources[1][2]
  • blockUntilReady · ratelimit-blockuntilready-no-try-catch
    error
    Whentimeout parameter is <= 0 OR underlying Redis network failure throws Error before blockUntilReady can resolve
    ThrowsError('timeout must be positive') | Error (network failure from Redis)
    Required handlingCaller MUST wrap ratelimit.blockUntilReady() in try-catch. The method throws synchronously if timeout <= 0, and can propagate Redis network errors.
    costmediumin prodimmediate exceptionusers seeservice unavailablevisibilityvisible
    Sources[1]
  • resetUsedTokens · ratelimit-resetusedtokens-no-try-catch
    error
    WhenUnderlying Redis HTTP call fails due to network failure or auth error. Unlike limit(), resetUsedTokens() does NOT have a timeout/fail-open mechanism — it will always propagate the Redis error to the caller.
    ThrowsError (network failure or auth error from @upstash/redis HTTP client)
    Required handlingCaller MUST wrap ratelimit.resetUsedTokens() in try-catch. Unlike limit(), there is no built-in timeout/fail-open for this method. A Redis failure during an admin reset operation will throw and crash the calling request handler.
    costlowin prodimmediate exceptionusers seeservice unavailablevisibilityvisible
    Sources[3][1]
  • getRemaining · ratelimit-getremaining-no-try-catch
    error
    WhenUnderlying Redis HTTP call fails due to network failure or auth error. getRemaining() has no timeout or fail-open mechanism — it propagates all Redis errors to the caller.
    ThrowsError (network failure or auth error from @upstash/redis HTTP client)
    Required handlingCaller MUST wrap ratelimit.getRemaining() in try-catch. Used in response headers (X-RateLimit-Remaining) or dashboard endpoints — an unhandled Redis error here crashes the API response. Fail gracefully by returning cached or default values when Redis is unreachable.
    costlowin prodimmediate exceptionusers seedegraded performancevisibilityvisible
    Sources[3][1]
  • setDynamicLimit · ratelimit-setdynamiclimit-not-enabled
    error
    WhenCalled when dynamicLimits was NOT set to true in the Ratelimit constructor. Throws synchronously before any Redis call is made.
    ThrowsError('dynamicLimits must be enabled in the Ratelimit constructor to use setDynamicLimit()')
    Required handlingCaller MUST wrap setDynamicLimit() in try-catch when dynamicLimits enablement is not guaranteed at the call site. This is a configuration error that indicates a code bug — the constructor option must be set to use this method.
    costlowin prodimmediate exceptionusers seeservice unavailablevisibilityvisible
    Sources[3][1]
  • setDynamicLimit · ratelimit-setdynamiclimit-redis-failure
    error
    WhendynamicLimits is enabled but the underlying Redis SET or DEL call fails due to network failure or auth error.
    ThrowsError (network failure from @upstash/redis HTTP client)
    Required handlingCaller MUST wrap setDynamicLimit() in try-catch. A failure to set a dynamic limit means the override was NOT applied — the rate limiter will continue using the old limit. This is especially dangerous in incident response scenarios where operators use setDynamicLimit() to throttle load.
    costmediumin prodimmediate exceptionusers seedegraded performancevisibilityvisible
    Sources[3]
  • getDynamicLimit · ratelimit-getdynamiclimit-not-enabled
    error
    WhenCalled when dynamicLimits was NOT set to true in the Ratelimit constructor. Throws synchronously, identical pattern to setDynamicLimit.
    ThrowsError('dynamicLimits must be enabled in the Ratelimit constructor to use getDynamicLimit()')
    Required handlingCaller MUST wrap getDynamicLimit() in try-catch when dynamicLimits enablement is not guaranteed. This is a code configuration error.
    costlowin prodimmediate exceptionusers seeservice unavailablevisibilityvisible
    Sources[3]
  • getDynamicLimit · ratelimit-getdynamiclimit-redis-failure
    error
    WhendynamicLimits is enabled but the Redis GET call fails due to network failure or auth error.
    ThrowsError (network failure from @upstash/redis HTTP client)
    Required handlingCaller MUST wrap getDynamicLimit() in try-catch. Typically called in admin/monitoring endpoints — an uncaught error crashes the admin API.
    costlowin prodimmediate exceptionusers seedegraded performancevisibilityvisible
    Sources[3]
  • updateIpDenyList · ratelimit-updateipdenylist-threshold-error
    error
    Whenthreshold parameter is not an integer between 1 and 8 (inclusive). ThresholdError is thrown synchronously before any network call.
    ThrowsThresholdError('Allowed threshold values are from 1 to 8, 1 and 8 included. Received: <n>')
    Required handlingCaller MUST wrap updateIpDenyList() in try-catch and handle ThresholdError separately for clear error messaging. Pass a value from 1 to 8 where lower values include more (less certain) IPs and higher values are more conservative.
    costlowin prodimmediate exceptionusers seedegraded performancevisibilityvisible
    Sources[4]
  • updateIpDenyList · ratelimit-updateipdenylist-network-failure
    error
    WhenExternal HTTP fetch to https://raw.githubusercontent.com/stamparm/ipsum/master/levels fails (GitHub unreachable, DNS failure, non-200 response). The error is wrapped in Error('Failed to fetch ip deny list: ...').
    ThrowsError('Failed to fetch ip deny list: <original error>')
    Required handlingCaller MUST wrap updateIpDenyList() in try-catch. This function makes an external HTTP call to GitHub, not Upstash — it can fail independently of Redis availability. Run in a background job with retry logic rather than in a hot request path.
    costlowin prodimmediate exceptionusers seedegraded performancevisibilitysilent
    Sources[4]
  • disableIpDenyList · ratelimit-disableipdenylist-redis-failure
    error
    WhenRedis multi-command transaction (SDIFFSTORE, DEL, SET) fails due to network failure or auth error. The deny list is NOT disabled if this throws.
    ThrowsError (network failure from @upstash/redis HTTP client)
    Required handlingCaller MUST wrap disableIpDenyList() in try-catch. A failure here means the IP deny list remains active — requests from blocked IPs continue to be rejected. Used in emergency scenarios (false positives blocking legitimate users) so uncaught failure is operationally dangerous.
    costmediumin prodimmediate exceptionusers seedegraded performancevisibilityvisible
    Sources[4]

Sources

Every postcondition cites at least one of these. Grouped by source type; numbered to match the footnotes above.

Official documentation
  • [2]
    upstash.com/docs/redis/sdks
    Features
  • [3]
    upstash.com/docs/redis/sdks
    Methods
Source code

Research notes

Curator notes from SOURCES.md captured when the profile was written so you can verify the reasoning, not just the rules.

Sources — @upstash/ratelimit

All URLs fetched on 2026-04-02.

Package Metadata

Documentation

Source Code (fetched directly)

Key Findings

  • TimeoutError class is exported but limit() does NOT throw it — timeout resolves with { success: true, reason: "timeout" }
  • Underlying @upstash/redis HTTP calls CAN throw (network, 401 auth errors)
  • Real-world usage pattern: calling limit() without try-catch is common (roomGPT, lagon)
  • No known CVEs as of 2026-04-02 (checked socket.dev, aikido.dev)
Need a different package?
Request a profile