Ratelock

Resilience Policies

withFallback

Define behavior when the rate limiter throws an error.

The withFallback policy defines what happens when the underlying rate limiter throws an error (e.g. database or network failure). Choose between failing open (allow), failing closed (deny), or propagating the error.

Usage

import { fixedWindow, withFallback } from '@ratelock/redis'

const limiter = await fixedWindow({ ... })

// Fail-open: allow requests when the backend is unreachable
const allowPolicy = withFallback(limiter, 'allow')

// Fail-closed: deny requests when the backend is unreachable
const denyPolicy = withFallback(limiter, 'deny')

// Propagate the error (default behavior without policy wrapper)
const throwPolicy = withFallback(limiter, 'throw')

// Optionally provide default result fields used when the limiter throws
const withDefaults = withFallback(limiter, 'allow', { remaining: 0, reset: 0 })

Configuration

The second argument is the FallbackPolicy itself (a string). An optional third argument lets you provide default result fields used when the limiter throws:

withFallback(limiter, 'allow')
withFallback(limiter, 'allow', { remaining: 0, reset: Date.now() + 60_000 })

FallbackPolicy: 'throw' | 'allow' | 'deny'

PolicyBehaviorUse Case
'allow'Returns { allowed: true } on errorPrefer availability over strict rate limiting
'deny'Returns { allowed: false } on errorPrefer safety - better to deny than allow abuse
'throw'Re-throws the errorLet the caller handle the error

Built-in Alternative

For most cases, use the built-in fallback option at creation time instead:

import { fixedWindow } from '@ratelock/redis'

const limiter = await fixedWindow({
    url: 'redis://localhost:6379',
    limit: 100,
    windowMs: 60_000,
    fallback: 'allow',
})

See Resilience Policies for when to use standalone vs built-in.

How is this guide?

Last updated on

On this page