How do Lua scripts work in Redis and why are they atomic?
Understand how Redis runs Lua scripts with EVAL and EVALSHA, and why single-threaded execution makes them atomic. Examples, pitfalls and interview guidance.
Expected Interview Answer
Redis embeds a Lua interpreter and runs a whole script as a single command via EVAL, and because Redis executes commands on one thread, the entire script runs to completion with no other command interleaved — making it atomic.
You send the script text with EVAL (or a cached SHA-1 hash with EVALSHA) plus the keys and arguments it touches. Redis blocks the server for the duration of the script, so every Redis call inside it — reads and writes — happens as an indivisible unit with no race window. This lets you implement check-then-set logic, counters, and rate limiters safely without extra round trips. The trade-off is that a slow script stalls every other client, so scripts must be short and deterministic, avoiding non-deterministic sources unless replicated by effects.
- Atomic multi-step logic with no interleaving
- Eliminates race conditions in read-modify-write flows
- Fewer network round trips than multiple commands
- EVALSHA caches scripts by SHA-1 to save bandwidth
- Keys declared explicitly, keeping cluster routing correct
AI Mentor Explanation
A Lua script is like an over bowled by one bowler with no drinks break, no fielding change, and no interruption allowed until all six balls are done. Because the umpire lets nobody onto the pitch mid-over, whatever happens across those deliveries lands as one indivisible passage of play rather than a jumble mixed with other events.
Step-by-Step Explanation
Step 1
Write the script
Author Lua that reads KEYS[] and ARGV[] and calls redis.call() for each Redis operation it needs.
Step 2
Send it with EVAL
Call EVAL script numkeys key... arg...; declare every key so cluster routing and analysis work.
Step 3
Redis runs it atomically
The single-threaded server executes the whole script with no other command interleaved.
Step 4
Return a value
The script returns a reply (number, string, table) that Redis converts and sends back to the client.
Step 5
Cache with EVALSHA
Load the script once, then invoke it by its SHA-1 hash to avoid resending the body each time.
What Interviewer Expects
- Knowledge of EVAL and EVALSHA
- Understanding that atomicity comes from single-threaded execution
- Why scripts must declare their keys
- Awareness that long scripts block the server
- The need for determinism and effect replication
Common Mistakes
- Thinking atomicity requires locks rather than single-threaded execution
- Accessing keys not passed via KEYS[] in a cluster
- Writing long-running scripts that stall other clients
- Using non-deterministic calls like random or time without care
- Confusing EVAL scripts with MULTI/EXEC transactions
Best Answer (HR Friendly)
“Redis can run a small Lua program as one command. Because Redis handles one thing at a time, the whole program runs from start to finish without anything else sneaking in, so multi-step logic like a counter or rate limiter stays safe from race conditions.”
Code Example
-- EVAL <script> 1 mykey expected new
-- Only set the key if it still holds the expected value
local current = redis.call('GET', KEYS[1])
if current == ARGV[1] then
redis.call('SET', KEYS[1], ARGV[2])
return 1
end
return 0Follow-up Questions
- What is the difference between EVAL and EVALSHA?
- How do Lua scripts differ from MULTI/EXEC transactions?
- Why must all keys be declared in the KEYS array?
- What happens if a script runs too long?
- How does Redis handle non-deterministic commands in scripts?
MCQ Practice
1. Why are Redis Lua scripts atomic?
Redis is single-threaded, so a script executes to completion before any other command runs, making it atomic.
2. What does EVALSHA let you do?
EVALSHA runs a previously loaded script by its SHA-1 digest, avoiding resending the whole body each call.
3. Why should keys be passed through the KEYS array?
Declaring keys lets Redis Cluster ensure all keys map to the same slot and route the command correctly.
Flash Cards
How do you run a Lua script in Redis? — With EVAL script numkeys key... arg..., or EVALSHA using the script's SHA-1 hash.
Why is a Lua script atomic? — Redis is single-threaded, so the whole script runs to completion with no other command interleaved.
What is EVALSHA for? — Running a cached script by SHA-1 hash so you don't resend the full body each time.
Why declare keys in KEYS[]? — So Redis Cluster can route the command and verify all keys share a slot.
Main risk of Lua scripts? — A long or looping script blocks the single-threaded server, stalling all other clients.