Redis Atomicity Toolkit: Lua Scripts, Pipelining, and MULTI/EXEC
Fast recall
Quick revision
Core answer
Whether the candidate understands the practical differences between Redis's three command-grouping mechanisms and can choose the right tool for problems like atomic counters with conditional logic, bulk inserts, and rate limiting.
Confusing pipelining (a network optimization) with transactions (an atomicity primitive); thinking MULTI/EXEC provides rollback semantics like SQL transactions; or writing a Lua script that runs forever and blocks the entire Redis server.
Mention that Lua scripts must be deterministic and short (Redis is single-threaded; long scripts block all clients), discuss SCRIPT LOAD + EVALSHA for caching scripts on the server, and compare Lua's atomicity model to Redis Functions (Redis 7+) which are the modern replacement.
Interview-ready guide
Interview answer
Redis offers three different mechanisms for grouping commands, and they solve different problems. Conflating them — especially treating pipelining as a transaction — is one of the most common mistakes I see.
Pipelining — throughput, not atomicity
- Pipelining sends multiple commands in one network round trip and reads all responses back together; it's purely a latency optimization
- There's no atomicity — other clients can execute commands between any two of mine; if I pipeline
GET counter; INCR counter, another client can modify counter in between - Use it when you need to bulk-load 10,000 keys or fan out 100 reads — anywhere throughput matters and ordering doesn't
MULTI/EXEC — atomic command groups
- MULTI/EXEC queues commands on the server and executes them as one atomic block — no other client's commands interleave
- Two surprises: there's no rollback (a runtime error in one queued command doesn't undo the others), and there's no conditional logic (you can't decide what to queue based on values read during the transaction)
- WATCH adds optimistic concurrency — watch a key, read it, build a transaction based on the value, EXEC; if anyone modified the key in between, EXEC returns nil and you retry
- Useful for simple atomic groups; under contention, the retry loop can become wasteful
Lua scripts — atomicity with logic
- Lua scripts run server-side as a single atomic operation; they can read values, branch on them, compute, and write results — all without interleaving
- This is the only way to express "check the counter; if below the limit, increment and set TTL; otherwise reject" as one atomic operation
- Critical caveat: Redis is single-threaded, so a Lua script blocks every other client until it completes; keep scripts short (microseconds), deterministic, and pass keys via the KEYS array for cluster compatibility
- Spring Data Redis caches scripts via EVALSHA automatically; on Redis 7+, prefer the new Functions API over ad-hoc EVAL
The decision in practice: pipelining for bulk operations without atomicity, MULTI/EXEC for simple unconditional atomic groups, Lua for anything requiring read-then-write decisions. For rate limiters and distributed locks, the answer is almost always Lua.
Redis Atomicity Toolkit: Lua Scripts, Pipelining, and MULTI/EXEC
Direct Answer
Redis offers three mechanisms for grouping commands: pipelining batches commands into one network round trip without atomicity, MULTI/EXEC transactions queue commands and execute them atomically with optimistic concurrency via WATCH, and Lua scripts run server-side as a single atomic operation with conditional logic and the ability to compute on the data. Use pipelining purely for throughput, MULTI/EXEC for simple atomic groups with optimistic locking, and Lua scripts when you need conditional branching, server-side computation, or atomicity guarantees that span reads and writes.
Common Mistakes & Pitfalls
Confusing pipelining (a network optimization) with transactions (an atomicity primitive); thinking MULTI/EXEC provides rollback semantics like SQL transactions; or writing a Lua script that runs forever and blocks the entire Redis server.
Check your understanding
Answer these without looking back at the article.
- How does Redis prevent a long-running Lua script from indefinitely blocking the server?
- Why does WATCH-MULTI-EXEC become inefficient under high contention compared to a Lua script?
- What is the difference between Redis Functions (Redis 7+) and EVAL/EVALSHA scripts?
Related interview prep categories
1Looking for a structured roadmap?
Every module on this page is also part of the full Java backend interview track.