April’s release replaces EVAL with a registry of named, versioned functions that survive a restart and replicate to replicas.
#!lua name=ratelimit
local function hit(keys, args)
local n = redis.call('INCR', keys[1])
if n == 1 then redis.call('EXPIRE', keys[1], args[1]) end
return n
end
redis.register_function('rl_hit', hit)
-- FUNCTION LOAD REPLACE "$(cat ratelimit.lua)"
-- FCALL rl_hit 1 rl:user:4471 60
A SHA that nobody can map back to source was the actual problem with scripts, and a named library with a version makes deployment a step rather than a hope. It is still single-threaded and still blocks every other client for the duration, so the discipline about keeping functions to a handful of commands is unchanged.