Generate race-free Redis Lua scripts
Whenever you read a Redis value, make a decision, and write it back as separate commands, you have a race condition: another client can change the value in between. A Lua script runs atomically on the server, so the whole read-decide-write happens as one indivisible step. This builder produces correct, documented Lua for the three patterns that need atomicity most.
How it works
Pick a pattern and the builder emits a complete script plus its KEYS/ARGV contract:
- Rate limiter —
INCRthe window counter; on the first hit setEXPIREto the window length; return1if the count is within the limit, else0. Because increment and check are atomic, bursts cannot slip past the limit. - Distributed lock — acquire with
SET key token NX PX ttl(returns whether the lock was taken); release byGET-ing the key, comparing it to your token, and onlyDEL-ing on a match so you never release someone else’s lock. - Atomic counter —
INCRBYby a step and set a TTL on first creation, returning the new value, useful for quotas and metrics that must not lose updates.
Each script uses KEYS[1] for the key and ARGV[…] for limits, TTLs, and tokens, with a comment block documenting every parameter and an example EVAL call wired to your chosen defaults.
Tips and notes
- Load the script once with
SCRIPT LOADand invoke it by hash withEVALSHAto avoid sending the body on every call. - Pass the current time from your application as an
ARGVvalue rather than callingTIMEinside the script — that keeps the script deterministic and replication-safe. - In Redis Cluster, every key a script touches must be in
KEYSand hash to the same slot; do not construct key names fromARGV. - For the lock, set the TTL longer than your worst-case critical section, and treat a failed acquire as “retry with backoff”, not an error.