Command Palette

Search for a command to run...

Hectal
PHASE 3Intermediate ~9 min· topic 4 of 5

Topic 3.4

Redis Functions: Server-Side Logic as a Deployed Artifact

In one line

Redis Functions (7.0+) are named Lua functions grouped into libraries, loaded once with FUNCTION LOAD, called with FCALL, and persisted and replicated like data. They fix the script-cache problems of EVALSHA and give server-side logic a versioned deployment lifecycle.

0/5 · 0%

Think of it like this

The difference between emailing a recipe to the kitchen every time you want a dish (EVAL) and adding it to the kitchen's official recipe book (FUNCTION LOAD). Once it's in the book, cooks can make it by name, new kitchens get a copy of the book, and you update it deliberately with a new edition.

Key ideas

  1. 01

    A library is Lua code that starts with a shebang naming the engine and library: #!lua name=ratelimit, and registers functions with redis.register_function('allow', function(keys, args) ... end) or the table form with flags (for example no-writes for read-only functions, callable with FCALL_RO).

  2. 02

    Lifecycle commands: FUNCTION LOAD [REPLACE] code, FUNCTION LIST [WITHCODE], FUNCTION DELETE lib, FUNCTION DUMP / FUNCTION RESTORE (export and import all libraries), FUNCTION FLUSH, FUNCTION STATS, and FUNCTION KILL (for a running read-only function).

  3. 03

    Functions are part of the dataset: saved in RDB and AOF, replicated to replicas, and present after a restart or failover. No more NOSCRIPT surprises, and every client calls the same version by name instead of each app shipping its own copy of a script.

  4. 04

    Execution is identical to Lua scripts: atomic, blocking while running, same busy-reply-threshold, same cluster rule that all keys must share a slot. In Redis Cluster, functions must be loaded on every primary (replicas get them via replication); tooling like redis-cli --cluster call helps.

  5. 05

    Versioning strategy: include a version in the library or function name (ratelimit_v2.allow), deploy the new version alongside the old one, switch clients over, then delete the old library. That mirrors how you'd roll out a database migration.

  6. 06

    Use scripts (EVAL) for logic owned by one application and shipped with it; use Functions when logic is shared by several services, needs to survive restarts without client reloads, or is managed by a platform team.

Code & diagrams

ratelimit-lib.lualua
#!lua name=ratelimit_v1

local function allow(keys, args)
  local limit, window = tonumber(args[1]), tonumber(args[2])
  local current = redis.call('INCR', keys[1])
  if current == 1 then redis.call('EXPIRE', keys[1], window) end
  if current > limit then return 0 end
  return 1
end

local function remaining(keys, args)
  local used = tonumber(redis.call('GET', keys[1]) or '0')
  return math.max(0, tonumber(args[1]) - used)
end

redis.register_function('rl_allow', allow)
redis.register_function{
  function_name = 'rl_remaining',
  callback = remaining,
  flags = { 'no-writes' }          -- callable with FCALL_RO, even on replicas
}
functions.shbash
# Load (or replace) the library
cat ratelimit-lib.lua | redis-cli -x FUNCTION LOAD REPLACE
"ratelimit_v1"

redis-cli FCALL rl_allow 1 rl:{user:42}:28792000 100 60
(integer) 1
redis-cli FCALL_RO rl_remaining 1 rl:{user:42}:28792000 100
(integer) 99

redis-cli FUNCTION LIST LIBRARYNAME ratelimit
1) 1) "library_name"  2) "ratelimit_v1"  3) "engine"  4) "LUA"
   5) "functions" ...

# Load on every primary of a cluster
redis-cli --cluster call 10.0.0.1:6379 FUNCTION LOAD REPLACE "$(cat ratelimit-lib.lua)"

# Back up and restore all libraries
redis-cli --no-raw FUNCTION DUMP > functions.dump

Interview problem

The problem

Rolling out shared server-side logic

Five services use the same rate-limiting Lua script, each shipping its own copy. After a Redis failover, some services start failing with NOSCRIPT, and two copies of the script have drifted apart. Propose how to fix this with Functions and how to deploy a new version safely.

The interviewer follows up

01

What happens to functions when you add a new shard to a cluster?

Explain it without notes

01

How do Functions differ from EVAL scripts in lifecycle and persistence?

02

What does the no-writes flag allow?

Practice

01

Convert the inventory purchase script from Topic 3.2 into a Functions library with buy and a read-only stock_left.

Trade-offs

  • ↔

    Functions give durable, shared, versioned logic but add a deployment step and an admin permission to manage.

  • ↔

    Like scripts, functions block the server while running; they aren't a place for heavy computation.

Done when you can

  • I can write, load, call, list and delete a function library.

  • I can deploy a new function version without downtime.

  • I know when to choose Functions over EVAL.