RateLimiter.ts
RateLimiter.ts overview
Section titled “RateLimiter.ts overview”Coordinates rate limits through shared persistent storage.
The RateLimiter service consumes tokens for string keys using fixed-window
counters or token-bucket state. It can protect external APIs, enforce quotas,
or throttle workers across fibers and processes that share the same store.
This module includes helpers that fail when a limit is exceeded, return the
delay needed before continuing, or wrap an effect so it waits automatically.
It also defines the store service and in-memory or Redis-backed store layers.
Since v4.0.0
Exports Grouped by Category
Section titled “Exports Grouped by Category”RateLimiterStore
Section titled “RateLimiterStore”layerStoreMemory
Section titled “layerStoreMemory”Provides a process-local in-memory RateLimiterStore.
Signature
declare const layerStoreMemory: Layer.Layer<RateLimiterStore, never, never>Since v4.0.0
makeStoreRedis
Section titled “makeStoreRedis”Creates a Redis-backed RateLimiterStore using Lua scripts and the
configured key prefix.
Signature
declare const makeStoreRedis: ( options?: { readonly prefix?: string | undefined } | undefined) => Effect.Effect< { readonly fixedWindow: (options: { readonly key: string readonly tokens: number readonly refillRate: Duration.Duration readonly limit: number | undefined }) => Effect.Effect<readonly [count: number, ttl: number], RateLimiterError> readonly tokenBucket: (options: { readonly key: string readonly tokens: number readonly limit: number readonly refillRate: Duration.Duration readonly allowOverflow: boolean }) => Effect.Effect<number, RateLimiterError> readonly adaptiveConsume: ( options: AdaptiveConsumeOptions ) => Effect.Effect<AdaptiveConsumeResult, RateLimiterError> readonly adaptiveFeedback: (options: AdaptiveFeedbackOptions) => Effect.Effect<void, RateLimiterError> }, never, Redis.Redis>Since v4.0.0
accessors
Section titled “accessors”makeSleep
Section titled “makeSleep”Accesses a function that sleeps when the rate limit is exceeded.
Example (Sleeping until rate limit permits)
import { Effect } from "effect"import { RateLimiter } from "effect/unstable/persistence"
Effect.gen(function* () { // Access the `sleep` function from the RateLimiter module const sleep = yield* RateLimiter.makeSleep
// Use the `sleep` function with specific rate limiting parameters. // This will only sleep if the rate limit has been exceeded. yield* sleep({ key: "some-key", limit: 10, window: "5 seconds", algorithm: "fixed-window" })})Signature
declare const makeSleep: Effect.Effect< (options: { readonly algorithm?: "fixed-window" | "token-bucket" | undefined readonly window: Duration.Input readonly limit: number readonly key: string readonly tokens?: number | undefined }) => Effect.Effect<ConsumeResult, RateLimiterError>, never, RateLimiter>Since v4.0.0
makeWithRateLimiter
Section titled “makeWithRateLimiter”Accesses a function that applies rate limiting to an effect.
Example (Applying rate limits to effects)
import { Effect } from "effect"import { RateLimiter } from "effect/unstable/persistence"
Effect.gen(function* () { // Access the `withLimiter` function from the RateLimiter module const withLimiter = yield* RateLimiter.makeWithRateLimiter
// Apply a rate limiter to an effect yield* Effect.log("Making a request with rate limiting").pipe( withLimiter({ key: "some-key", limit: 10, onExceeded: "delay", window: "5 seconds", algorithm: "fixed-window" }) )})Signature
declare const makeWithRateLimiter: Effect.Effect< (options: { readonly algorithm?: "fixed-window" | "token-bucket" | undefined readonly onExceeded?: "delay" | "fail" | undefined readonly window: Duration.Input readonly limit: number readonly key: string readonly tokens?: number | undefined }) => <A, E, R>(effect: Effect.Effect<A, E, R>) => Effect.Effect<A, E | RateLimiterError, R>, never, RateLimiter>Since v4.0.0
constructors
Section titled “constructors”Creates a RateLimiter from the current RateLimiterStore.
Details
The limiter supports fixed-window and token-bucket algorithms and either fails or returns a delay when a limit is exceeded.
Signature
declare const make: Effect.Effect<RateLimiter, never, RateLimiterStore>Since v4.0.0
errors
Section titled “errors”RateLimitExceeded (class)
Section titled “RateLimitExceeded (class)”Error reason for a rate-limit check that exceeded the configured limit.
Details
Includes the affected key, limit, remaining token count, and retry delay.
Signature
declare class RateLimitExceededSince v4.0.0
RateLimitStoreError (class)
Section titled “RateLimitStoreError (class)”Error reason for failures in the backing RateLimiterStore.
Signature
declare class RateLimitStoreErrorSince v4.0.0
RateLimiterError (class)
Section titled “RateLimiterError (class)”Error raised by rate limiter operations, wrapping a concrete failure
reason.
Signature
declare class RateLimiterError { constructor(props: { readonly reason: RateLimiterErrorReason })}Since v4.0.0
[ErrorTypeId] (property)
Section titled “[ErrorTypeId] (property)”Marks this value as a rate limiter error for runtime guards.
Signature
readonly [ErrorTypeId]: "~@effect/experimental/RateLimiter/RateLimiterError"Since v4.0.0
RateLimiterErrorReason
Section titled “RateLimiterErrorReason”Schema for all reasons that can be carried by RateLimiterError.
Signature
declare const RateLimiterErrorReason: Schema.Union<[typeof RateLimitExceeded, typeof RateLimitStoreError]>Since v4.0.0
RateLimiterErrorReason (type alias)
Section titled “RateLimiterErrorReason (type alias)”Union of reasons carried by RateLimiterError.
Signature
type RateLimiterErrorReason = RateLimitExceeded | RateLimitStoreErrorSince v4.0.0
layers
Section titled “layers”Provides RateLimiter using the current RateLimiterStore.
Signature
declare const layer: Layer.Layer<RateLimiter, never, RateLimiterStore>Since v4.0.0
layerStoreRedis
Section titled “layerStoreRedis”Provides a Redis-backed RateLimiterStore using makeStoreRedis.
Signature
declare const layerStoreRedis: (options?: { readonly prefix?: string | undefined}) => Layer.Layer<RateLimiterStore, never, Redis.Redis>Since v4.0.0
layerStoreRedisConfig
Section titled “layerStoreRedisConfig”Provides a Redis-backed RateLimiterStore from wrapped configuration
options.
Signature
declare const layerStoreRedisConfig: ( options: Config.Wrap<{ readonly prefix?: string | undefined }>) => Layer.Layer<RateLimiterStore, Config.ConfigError, Redis.Redis>Since v4.0.0
models
Section titled “models”AdaptiveConsumeOptions (interface)
Section titled “AdaptiveConsumeOptions (interface)”Options for consuming tokens from the adaptive rate limiter store.
Signature
export interface AdaptiveConsumeOptions { /** * The rate-limit key. */ readonly key: string
/** * The number of tokens to consume. */ readonly tokens: number
/** * The fallback limit configured for the regular rate limiter. */ readonly fallbackLimit: number
/** * The fallback window configured for the regular rate limiter. */ readonly fallbackWindow: Duration.Duration}Since v4.0.0
AdaptiveConsumeResult (interface)
Section titled “AdaptiveConsumeResult (interface)”Metadata returned after consuming tokens from the adaptive rate limiter store.
Signature
export interface AdaptiveConsumeResult { /** * The amount of delay to wait before making the request. */ readonly delay: Duration.Duration
/** * The adaptive state epoch used to correlate later response feedback. */ readonly epoch: number
/** * The adaptive phase observed by this consume operation. */ readonly phase: AdaptivePhase}Since v4.0.0
AdaptiveFeedbackOptions (interface)
Section titled “AdaptiveFeedbackOptions (interface)”Options for reporting response feedback to the adaptive rate limiter store.
Signature
export interface AdaptiveFeedbackOptions { /** * The rate-limit key. */ readonly key: string
/** * The adaptive state epoch returned by `adaptiveConsume`. */ readonly epoch: number
/** * The number of tokens consumed by the request. */ readonly tokens: number
/** * The HTTP response status code. */ readonly status: number
/** * The parsed `Retry-After` delay, when present. */ readonly retryAfter: Duration.Duration | undefined}Since v4.0.0
AdaptivePhase (type alias)
Section titled “AdaptivePhase (type alias)”Phase of adaptive rate limiting driven by server feedback.
Signature
type AdaptivePhase = "inactive" | "cooldown" | "learning" | "learned"Since v4.0.0
ConsumeResult (interface)
Section titled “ConsumeResult (interface)”Metadata returned after consuming tokens from a rate limiter.
Signature
export interface ConsumeResult { /** * The amount of delay to wait before making the next request, when the rate * limiter is using the "delay" `onExceeded` strategy. It will be * Duration.zero if the request is allowed immediately. */ readonly delay: Duration.Duration
/** * The maximum number of requests allowed in the current window. */ readonly limit: number
/** * The number of remaining requests in the current window. */ readonly remaining: number
/** * The time until the rate limit fully resets. */ readonly resetAfter: Duration.Duration}Since v4.0.0
RateLimiter (interface)
Section titled “RateLimiter (interface)”Service for consuming rate-limit tokens for a key using fixed-window or token-bucket algorithms.
Signature
export interface RateLimiter { readonly [TypeId]: TypeId
readonly consume: (options: { readonly algorithm?: "fixed-window" | "token-bucket" | undefined readonly onExceeded?: "delay" | "fail" | undefined readonly window: Duration.Input readonly limit: number readonly key: string readonly tokens?: number | undefined }) => Effect.Effect<ConsumeResult, RateLimiterError>
readonly adaptiveConsume: (options: AdaptiveConsumeOptions) => Effect.Effect<AdaptiveConsumeResult, RateLimiterError>
readonly adaptiveFeedback: (options: AdaptiveFeedbackOptions) => Effect.Effect<void, RateLimiterError>}Since v4.0.0
services
Section titled “services”RateLimiter
Section titled “RateLimiter”Service tag for persistent token-consumption services.
When to use
Use to access or provide rate-limit checks backed by fixed-window counters or token-bucket state.
Signature
declare const RateLimiter: Context.Service<RateLimiter, RateLimiter>Since v4.0.0
RateLimiterStore (class)
Section titled “RateLimiterStore (class)”Defines the low-level backing store for rate-limit state.
When to use
Use to provide the shared counter storage and adaptive feedback state used by persistent rate-limit checks.
Signature
declare class RateLimiterStoreSince v4.0.0
type IDs
Section titled “type IDs”ErrorTypeId
Section titled “ErrorTypeId”Runtime type identifier for RateLimiterError.
Signature
declare const ErrorTypeId: "~@effect/experimental/RateLimiter/RateLimiterError"Since v4.0.0
ErrorTypeId (type alias)
Section titled “ErrorTypeId (type alias)”Type-level identifier used to brand RateLimiterError values.
Signature
type ErrorTypeId = "~@effect/experimental/RateLimiter/RateLimiterError"Since v4.0.0
TypeId
Section titled “TypeId”Runtime type identifier for RateLimiter values.
Signature
declare const TypeId: "~effect/persistence/RateLimiter"Since v4.0.0
TypeId (type alias)
Section titled “TypeId (type alias)”Type-level identifier used to brand RateLimiter values.
Signature
type TypeId = "~effect/persistence/RateLimiter"Since v4.0.0