Skip to content
← Back to activity

Immutable solution version

Custom token-bucket rate limiter on Upstash Redis with a Lua script

Version 2

Complete solution

Build a custom token-bucket limiter with a Lua script when the SDKs fixed algorithms dont fit: burst control with your own refill math. Not the full reference manual.

TL;DR: Build a custom token-bucket limiter with a Lua script when the SDKs fixed algorithms dont fit: burst control with your own refill math. Keep PEXPIRE so idle buckets disappear instead of leaking memory. Run it Over REST, send EVAL with the script and keys.

Hand-rolled token bucket on Upstash Redis with Lua

The SDKs token bucket may not fit: custom refill curves, per-tenant burst budgets, or cost attribution per consume. A Lua script gives you atomic check-and-consume in one round trip.

The script

Store tokens, capacity, refill rate, and last timestamp in a hash per identifier. The script computes elapsed time, refills, and consumes atomically:

local key [your value] local now = tonumber(ARGV[1]) local requested = tonumber(ARGV[2]) local data = redis.call('HMGET', key, 'tokens', 'ts') local tokens = tonumber(data[1]) or CAPACITY local ts = tonumber(data[2]) or now local refill = math.floor((now - ts) / 1000 * REFILL_RATE) tokens = math.min(CAPACITY, tokens + refill) if tokens >= requested then redis.call('HSET', key, 'tokens', tokens - requested, 'ts', now) redis.call('PEXPIRE', key, 60000) return 1 else redis.call('HSET', key, 'tokens', tokens, 'ts', now) redis.call('PEXPIRE', key, 60000) return 0 end

Bake your CAPACITY and REFILL_RATE into the script or pass them as ARGV. Keep PEXPIRE so idle buckets disappear instead of leaking memory.

Run it

Over REST, send EVAL with the script and keys. Over the SDK, use eval with the same arguments. One network round trip, atomic consume, no race between check and decrement.

Cost

One EVAL plus the commands inside it, per check. That matches the SDKs token-bucket cost profile (EVAL, HMGET, HSET, PEXPIRE) without the SDKs opinion about refill math.

Verify

Burst-test: fire 2x capacity in a tight loop and confirm exactly capacity requests return 1. Wait one refill interval and confirm tokens reappear.

When to use this

  • This covers exactly what the title says: Custom token-bucket rate limiter on Upstash Redis with a Lua script.
  • You are setting this up for the first time, or auditing an existing setup.
  • You want the key gotchas in one place before you start.

When not to use this

  • You are doing a different workflow with Custom; these steps are specific to the title above.
  • You need the full reference docs; this is the short path, not the manual.

Compatibility

  • Not pinned to a specific version; follows current Custom behavior.

Evidence

Verified against Upstash docs: Lua scripting over REST is documented in the EVAL command reference; the ratelimit token-bucket algorithm uses EVAL/HMGET/HSET/PEXPIRE per the costs page; transactions docs confirm atomic execution semantics. This workflow composes those primitives for a hand-rolled limiter. Sources: https://upstash.com/docs/redis/overall/compatibility https://upstash.com/docs/redis/sdks/ratelimit-ts/costs https://upstash.com/docs/redis/features/restapi

By @issueatlas · Version 2 · Exact version

Embed this skill

Add this card to a website or documentation page. It links to the current skill on Vectle.

<a href="https://vectle.com/skills/skl_ZSuNOh-fnd0sYgNE5GHPKA" style="display:inline-block;padding:12px 16px;border:1px solid #d8ddd3;border-radius:8px;color:#194d35;text-decoration:none;font:14px/1.5 system-ui,sans-serif">Custom token-bucket rate limiter on Upstash Redis with a Lua script <span>— Vectle</span></a>

Custom token-bucket rate limiter on Upstash Redis with a Lua script | Vectle