{"id":46079,"library":"redis-bucket","title":"redis-bucket","description":"A Redis-backed leaky-bucket rate limiter (v2.0.0) that uses EVAL/EVALSHA-based Lua scripts for atomic operations, enabling shared rate-limiting across distributed instances without Redis modules. Supports tiered capacity and rate metrics with configurable backoff. Actively maintained with TypeScript types included. Compared to alternatives like express-rate-limit (in-memory), it provides centralized state; compared to ratelimiter (Redis-based with custom modules), it works on hosted Redis without module support.","status":"active","version":"2.0.0","language":"javascript","source_language":"en","source_url":"https://github.com/plsmphnx/redis-bucket","tags":["javascript","redis","leaky-bucket","rate","limit","capacity","typescript"],"install":[{"cmd":"npm install redis-bucket","lang":"bash","label":"npm"},{"cmd":"yarn add redis-bucket","lang":"bash","label":"yarn"},{"cmd":"pnpm add redis-bucket","lang":"bash","label":"pnpm"}],"dependencies":[{"reason":"Required for creating a Redis client to pass to the limiter; the library itself only needs eval/evalsha callbacks.","package":"redis","optional":false}],"imports":[{"note":"This library uses named exports; default import is incorrect in ESM. TypeScript types are included.","wrong":"import limiter from 'redis-bucket';","symbol":"create","correct":"import { create } from 'redis-bucket';"},{"note":"CommonJS require works but is less ideal for TypeScript; the namespace import matches the README pattern. ESM-only is not enforced, but require is less common.","wrong":"const limiter = require('redis-bucket');","symbol":"limiter module (namespace import)","correct":"import * as limiter from 'redis-bucket';"},{"note":"CapacityConfig is a TypeScript type, not a value. Use type-only import to avoid runtime errors.","wrong":"import { CapacityConfig } from 'redis-bucket'; (if using at runtime)","symbol":"CapacityConfig","correct":"import type { CapacityConfig } from 'redis-bucket';"}],"quickstart":{"code":"import { create } from 'redis-bucket';\nimport { createClient } from 'redis';\n\nconst client = createClient();\nclient.on('error', (err) => console.error('Redis Client Error', err));\n\nawait client.connect();\n\nconst limit = create({\n  capacity: { window: 60, min: 10, max: 20 },\n  backoff: (x) => 2 ** x,\n  eval: async (script, keys, argv) => {\n    return client.eval(script, { keys, arguments: argv.map(String) });\n  },\n  evalsha: async (sha, keys, argv) => {\n    return client.evalSha(sha, { keys, arguments: argv.map(String) });\n  },\n});\n\nconst result = await limit('user:123');\nconsole.log('Allow:', result.allow, 'Free:', result.free, 'Wait:', result.wait);\nawait client.disconnect();\n","lang":"typescript","description":"Creates a Redis client, connects, and initializes a rate limiter with capacity-based limits and exponential backoff."},"warnings":[{"fix":"Update callback signature to accept unknown[] and convert as needed.","message":"In v2.0.0, the 'eval' and 'evalsha' callbacks now receive an array of arguments (argv) as unknown[]; previously they were strings[]. Your callback must handle this type change.","severity":"breaking","affected_versions":">=2.0.0"},{"fix":"Provide evalsha callback to leverage script caching.","message":"The 'eval' callback is required; 'evalsha' is optional but highly recommended for performance. If evalsha is not provided, only EVAL is used (no script caching).","severity":"gotcha","affected_versions":">=1.0.0"},{"fix":"Migrate to v2 callback interface as shown in the API docs.","message":"In v1.x, the 'script' property was passed directly; in v2.x, the callbacks use different signatures. Old custom scripts will break.","severity":"deprecated","affected_versions":"<2.0.0"},{"fix":"Adjust logic that expects integer free values.","message":"From v2.0.0, the result property 'free' returns remaining capacity (not always an integer). In v1.x it was always an integer. Ensure your code handles fractional values.","severity":"breaking","affected_versions":">=2.0.0"},{"fix":"Use a Redis client with built-in reconnection (e.g., ioredis) or implement your own retry/handle in the eval callback.","message":"Redis client connection errors are not handled by the limiter; if the client disconnects, eval calls will throw. You must implement reconnection logic outside the library.","severity":"gotcha","affected_versions":">=1.0.0"},{"fix":"Update configuration to use the object format.","message":"In v2.0.0, the 'capacity' and 'rate' options no longer accept arrays of numbers; they require objects with 'window', 'min', 'max' (for capacity) or 'interval', 'rate' (for rate). Old numeric arrays will cause runtime errors.","severity":"breaking","affected_versions":">=2.0.0"},{"fix":"If upgrading, consider using exponential backoff or specify your own backoff function.","message":"The 'linear' backoff function was the default in v1.x; in v2.x, exponential is recommended but linear still works if explicitly provided.","severity":"deprecated","affected_versions":"<2.0.0"}],"env_vars":null,"search_vec":"'across':27 'activ':42 'altern':50 'atom':20 'back':7 'backoff':41 'base':68 'bucket':3,10,84 'capac':35,87 'central':61 'compar':48,63 'configur':40 'custom':70 'distribut':28 'enabl':22 'eval/evalsha-based':16 'express':53 'express-rate-limit':52 'host':75 'in-memori':56 'includ':47 'instanc':29 'javascript':80 'leaki':9,83 'leaky-bucket':8,82 'like':51 'limit':12,26,55,86 'lua':17 'maintain':43 'memori':58 'metric':38 'modul':32,71,78 'oper':21 'provid':60 'rate':11,25,37,54,85 'rate-limit':24 'ratelimit':65 'redi':2,6,31,67,76,81 'redis-back':5 'redis-bas':66 'redis-bucket':1 'script':18 'share':23 'state':62 'support':33,79 'tier':34 'type':46 'typescript':45,88 'use':15 'v2.0.0':13 'without':30,77 'work':73","created_at":"2026-06-07T12:58:11.397098+00:00","updated_at":"2026-06-07T12:58:11.397098+00:00","problems":[{"fix":"Use a standard Redis client like 'redis' or 'ioredis' that implements eval. Ensure you are passing the correct client reference.","cause":"Using an incompatible Redis client (e.g., a pool wrapper) that does not expose eval directly.","error":"TypeError: client.eval is not a function"},{"fix":"Configure your Redis client to automatically reconnect (e.g., enable retry strategy in ioredis or use a resilient client).","cause":"Redis connection lost before limit() calls. The limiter does not handle reconnection.","error":"Error: Connection closed (Error) at ..."},{"fix":"Use import { create } from 'redis-bucket' and then call create(config) to get the limit function.","cause":"Default import used instead of named import: import limiter from 'redis-bucket' returns an object with create, not a function.","error":"TypeError: limit is not a function"},{"fix":"Ensure eval/evalsha callbacks return the result from Redis client's eval/evalsha directly (array of values). Do not modify.","cause":"The eval callback is not returning the raw Redis reply correctly; the library expects a specific format.","error":"ERR wrong number of arguments for 'eval' command"},{"fix":"Update to redis-bucket@2.0.0 with npm install redis-bucket@latest. If locking, ensure @types are up to date.","cause":"Using an older version of the type definitions (v1.x) where result props were named differently (e.g., 'allowed').","error":"Property 'allow' does not exist on type 'Result' (TypeScript)"}],"ecosystem":"npm","meta_description":null,"install_score":null,"quickstart_score":null,"quickstart_tag":null,"pypi_latest":null,"cli_name":null,"cli_version":null,"type":"library","homepage":"https://github.com/plsmphnx/redis-bucket#readme","github":"https://github.com/plsmphnx/redis-bucket","docs":null,"changelog":null,"pypi":null,"npm":"redis-bucket","openapi_spec":null,"status_page":null,"smithery":null,"categories":["storage","testing"],"base_url":null,"auth_type":null,"provenance":{"verified_status":null,"verified_at":null,"last_verified":"2026-06-07","next_check":"2026-09-05","install_tag":null}}