{
  "id": "functions-intro",
  "title": "Redis functions",
  "url": "https://redis.io/docs/latest/develop/programmability/functions-intro/",
  "summary": "Scripting with Redis 7 and beyond",
  "tags": [
    "docs",
    "develop",
    "stack",
    "oss",
    "rs",
    "rc",
    "oss",
    "kubernetes",
    "clients"
  ],
  "last_updated": "2026-06-18T09:33:36-05:00",
  "page_type": "content",
  "content_hash": "f6af769ad19d5b507fc3cae85870d9b4144d5f782fcaa75bd935b79eec3ddfe2",
  "sections": [
    {
      "id": "overview",
      "title": "Overview",
      "role": "overview",
      "text": "Redis Functions is an API for managing code to be executed on the server. This feature, which became available in Redis 7, supersedes the use of [EVAL](https://redis.io/docs/latest/develop/programmability/eval-intro) in prior versions of Redis."
    },
    {
      "id": "prologue-or-what-s-wrong-with-eval-scripts",
      "title": "Prologue (or, what's wrong with Eval Scripts?)",
      "role": "content",
      "text": "Prior versions of Redis made scripting available only via the [`EVAL`](https://redis.io/docs/latest/commands/eval) command, which allows a Lua script to be sent for execution by the server.\nThe core use cases for [Eval Scripts](https://redis.io/docs/latest/develop/programmability/eval-intro) is executing part of your application logic inside Redis, efficiently and atomically.\nSuch script can perform conditional updates across multiple keys, possibly combining several different data types.\n\nUsing [`EVAL`](https://redis.io/docs/latest/commands/eval) requires that the application sends the entire script for execution every time.\nBecause this results in network and script compilation overheads, Redis provides an optimization in the form of the [`EVALSHA`](https://redis.io/docs/latest/commands/evalsha) command. By first calling [`SCRIPT LOAD`](https://redis.io/docs/latest/commands/script-load) to obtain the script's SHA1, the application can invoke it repeatedly afterward with its digest alone.\n\nBy design, Redis only caches the loaded scripts.\nThat means that the script cache can become lost at any time, such as after calling [`SCRIPT FLUSH`](https://redis.io/docs/latest/commands/script-flush), after restarting the server, or when failing over to a replica.\nThe application is responsible for reloading scripts during runtime if any are missing.\nThe underlying assumption is that scripts are a part of the application and not maintained by the Redis server.\n\nThis approach suits many light-weight scripting use cases, but introduces several difficulties once an application becomes complex and relies more heavily on scripting, namely:\n\n1. All client application instances must maintain a copy of all scripts. That means having some mechanism that applies script updates to all of the application's instances.\n1. Calling cached scripts within the context of a [transaction](https://redis.io/docs/latest/develop/using-commands/transactions) increases the probability of the transaction failing because of a missing script. Being more likely to fail makes using cached scripts as building blocks of workflows less attractive.\n1. SHA1 digests are meaningless, making debugging the system extremely hard (e.g., in a [`MONITOR`](https://redis.io/docs/latest/commands/monitor) session).\n1. When used naively, [`EVAL`](https://redis.io/docs/latest/commands/eval) promotes an anti-pattern in which scripts the client application renders verbatim scripts instead of responsibly using the [`KEYS` and `ARGV` Lua APIs](https://redis.io/docs/latest/develop/programmability/lua-api#runtime-globals).\n1. Because they are ephemeral, a script can't call another script. This makes sharing and reusing code between scripts nearly impossible, short of client-side preprocessing (see the first point).\n\nTo address these needs while avoiding breaking changes to already-established and well-liked ephemeral scripts, Redis v7.0 introduces Redis Functions."
    },
    {
      "id": "what-are-redis-functions",
      "title": "What are Redis Functions?",
      "role": "content",
      "text": "Redis functions are an evolutionary step from ephemeral scripting.\n\nFunctions provide the same core functionality as scripts but are first-class software artifacts of the database.\nRedis manages functions as an integral part of the database and ensures their availability via data persistence and replication.\nBecause functions are part of the database and therefore declared before use, applications aren't required to load them during runtime nor risk aborted transactions.\nAn application that uses functions depends only on their APIs rather than on the embedded script logic in the database.\n\nWhereas ephemeral scripts are considered a part of the application's domain, functions extend the database server itself with user-provided logic.\nThey can be used to expose a richer API composed of core Redis commands, similar to modules, developed once, loaded at startup, and used repeatedly by various applications / clients.\nEvery function has a unique user-defined name, making it much easier to call and trace its execution.\n\nThe design of Redis Functions also attempts to demarcate between the programming language used for writing functions and their management by the server.\nLua, the only language interpreter that Redis presently support as an embedded execution engine, is meant to be simple and easy to learn.\nHowever, the choice of Lua as a language still presents many Redis users with a challenge.\n\nThe Redis Functions feature makes no assumptions about the implementation's language.\nAn execution engine that is part of the definition of the function handles running it.\nAn engine can theoretically execute functions in any language as long as it respects several rules (such as the ability to terminate an executing function).\n\nPresently, as noted above, Redis ships with a single embedded [Lua 5.1](https://redis.io/docs/latest/develop/programmability/lua-api) engine.\nThere are plans to support additional engines in the future.\nRedis functions can use all of Lua's available capabilities to ephemeral scripts,\nwith the only exception being the [Redis Lua scripts debugger](https://redis.io/docs/latest/develop/programmability/lua-debugging).\n\nFunctions also simplify development by enabling code sharing.\nEvery function belongs to a single library, and any given library can consist of multiple functions.\nThe library's contents are immutable, and selective updates of its functions aren't allowed.\nInstead, libraries are updated as a whole with all of their functions together in one operation.\nThis allows calling functions from other functions within the same library, or sharing code between functions by using a common code in library-internal methods, that can also take language native arguments.\n\nFunctions are intended to better support the use case of maintaining a consistent view for data entities through a logical schema, as mentioned above.\nAs such, functions are stored alongside the data itself.\nFunctions are also persisted to the AOF file and replicated from master to replicas, so they are as durable as the data itself.\nWhen Redis is used as an ephemeral cache, additional mechanisms (described below) are required to make functions more durable.\n\nLike all other operations in Redis, the execution of a function is atomic.\nA function's execution blocks all server activities during its entire time, similarly to the semantics of [transactions](https://redis.io/docs/latest/develop/using-commands/transactions).\nThese semantics mean that all of the script's effects either have yet to happen or had already happened.\nThe blocking semantics of an executed function apply to all connected clients at all times.\nBecause running a function blocks the Redis server, functions are meant to finish executing quickly, so you should avoid using long-running functions."
    },
    {
      "id": "loading-libraries-and-functions",
      "title": "Loading libraries and functions",
      "role": "content",
      "text": "Let's explore Redis Functions via some tangible examples and Lua snippets.\n\nAt this point, if you're unfamiliar with Lua in general and specifically in Redis, you may benefit from reviewing some of the examples in [Introduction to Eval Scripts](https://redis.io/docs/latest/develop/programmability/eval-intro) and [Lua API](https://redis.io/docs/latest/develop/programmability/lua-api) pages for a better grasp of the language.\n\nEvery Redis function belongs to a single library that's loaded to Redis.\nLoading a library to the database is done with the [`FUNCTION LOAD`](https://redis.io/docs/latest/commands/function-load) command.\nThe command gets the library payload as input,\nthe library payload must start with Shebang statement that provides a metadata about the library (like the engine to use and the library name).\nThe Shebang format is:\n[code example]\n\nLet's try loading an empty library:\n\n[code example]\n\nThe error is expected, as there are no functions in the loaded library. Every library needs to include at least one registered function to load successfully.\nA registered function is named and acts as an entry point to the library.\nWhen the target execution engine handles the [`FUNCTION LOAD`](https://redis.io/docs/latest/commands/function-load) command, it registers the library's functions.\n\nThe Lua engine compiles and evaluates the library source code when loaded, and expects functions to be registered by calling the `redis.register_function()` API.\n\nThe following snippet demonstrates a simple library registering a single function named _knockknock_, returning a string reply:\n\n[code example]\n\nIn the example above, we provide two arguments about the function to Lua's `redis.register_function()` API: its registered name and a callback.\n\nWe can load our library and use [`FCALL`](https://redis.io/docs/latest/commands/fcall) to call the registered function:\n\n[code example]\n\nNotice that the [`FUNCTION LOAD`](https://redis.io/docs/latest/commands/function-load) command returns the name of the loaded library, this name can later be used [`FUNCTION LIST`](https://redis.io/docs/latest/commands/function-list) and [`FUNCTION DELETE`](https://redis.io/docs/latest/commands/function-delete).\n\nWe've provided [`FCALL`](https://redis.io/docs/latest/commands/fcall) with two arguments: the function's registered name and the numeric value `0`. This numeric value indicates the number of key names that follow it (the same way [`EVAL`](https://redis.io/docs/latest/commands/eval) and [`EVALSHA`](https://redis.io/docs/latest/commands/evalsha) work).\n\nWe'll explain immediately how key names and additional arguments are available to the function. As this simple example doesn't involve keys, we simply use 0 for now."
    },
    {
      "id": "input-keys-and-regular-arguments",
      "title": "Input keys and regular arguments",
      "role": "content",
      "text": "Before we move to the following example, it is vital to understand the distinction Redis makes between arguments that are names of keys and those that aren't.\n\nWhile key names in Redis are just strings, unlike any other string values, these represent keys in the database.\nThe name of a key is a fundamental concept in Redis and is the basis for operating the Redis Cluster.\n\n**Important:**\nTo ensure the correct execution of Redis Functions, both in standalone and clustered deployments, all names of keys that a function accesses must be explicitly provided as input key arguments.\n\nAny input to the function that isn't the name of a key is a regular input argument.\n\nNow, let's pretend that our application stores some of its data in Redis Hashes.\nWe want an [`HSET`](https://redis.io/docs/latest/commands/hset)-like way to set and update fields in said Hashes and store the last modification time in a new field named `_last_modified_`.\nWe can implement a function to do all that.\n\nOur function will call [`TIME`](https://redis.io/docs/latest/commands/time) to get the server's clock reading and update the target Hash with the new fields' values and the modification's timestamp.\nThe function we'll implement accepts the following input arguments: the Hash's key name and the field-value pairs to update.\n\nThe Lua API for Redis Functions makes these inputs accessible as the first and second arguments to the function's callback.\nThe callback's first argument is a Lua table populated with all key names inputs to the function.\nSimilarly, the callback's second argument consists of all regular arguments.\n\nThe following is a possible implementation for our function and its library registration:\n\n[code example]\n\nIf we create a new file named _mylib.lua_ that consists of the library's definition, we can load it like so (without stripping the source code of helpful whitespaces):\n\n[code example]\n\nWe've added the `REPLACE` modifier to the call to [`FUNCTION LOAD`](https://redis.io/docs/latest/commands/function-load) to tell Redis that we want to overwrite the existing library definition.\nOtherwise, we would have gotten an error from Redis complaining that the library already exists.\n\nNow that the library's updated code is loaded to Redis, we can proceed and call our function:\n\n[code example]\n\nIn this case, we had invoked [`FCALL`](https://redis.io/docs/latest/commands/fcall) with _1_ as the number of key name arguments.\nThat means that the function's first input argument is a name of a key (and is therefore included in the callback's `keys` table).\nAfter that first argument, all following input arguments are considered regular arguments and constitute the `args` table passed to the callback as its second argument."
    },
    {
      "id": "expanding-the-library",
      "title": "Expanding the library",
      "role": "content",
      "text": "We can add more functions to our library to benefit our application.\nThe additional metadata field we've added to the Hash shouldn't be included in responses when accessing the Hash's data.\nOn the other hand, we do want to provide the means to obtain the modification timestamp for a given Hash key.\n\nWe'll add two new functions to our library to accomplish these objectives:\n\n1. The `my_hgetall` Redis Function will return all fields and their respective values from a given Hash key name, excluding the metadata (i.e., the `_last_modified_` field).\n1. The `my_hlastmodified` Redis Function will return the modification timestamp for a given Hash key name.\n\nThe library's source code could look something like the following:\n\n[code example]\n\nWhile all of the above should be straightforward, note that the `my_hgetall` also calls [`redis.setresp(3)`](https://redis.io/docs/latest/develop/programmability/lua-api#redis.setresp).\nThat means that the function expects [RESP3](https://github.com/redis/redis-specifications/blob/master/protocol/RESP3.md) replies after calling `redis.call()`, which, unlike the default RESP2 protocol, provides dictionary (associative arrays) replies.\nDoing so allows the function to delete (or set to `nil` as is the case with Lua tables) specific fields from the reply, and in our case, the `_last_modified_` field.\n\nAssuming you've saved the library's implementation in the _mylib.lua_ file, you can replace it with:\n\n[code example]\n\nOnce loaded, you can call the library's functions with [`FCALL`](https://redis.io/docs/latest/commands/fcall):\n\n[code example]\n\nYou can also get the library's details with the [`FUNCTION LIST`](https://redis.io/docs/latest/commands/function-list) command:\n\n[code example]\n\nYou can see that it is easy to update our library with new capabilities."
    },
    {
      "id": "reusing-code-in-the-library",
      "title": "Reusing code in the library",
      "role": "content",
      "text": "On top of bundling functions together into database-managed software artifacts, libraries also facilitate code sharing.\nWe can add to our library an error handling helper function called from other functions.\nThe helper function `check_keys()` verifies that the input _keys_ table has a single key.\nUpon success it returns `nil`, otherwise it returns an [error reply](https://redis.io/docs/latest/develop/programmability/lua-api#redis.error_reply).\n\nThe updated library's source code would be:\n\n[code example]\n\nAfter you've replaced the library in Redis with the above, you can immediately try out the new error handling mechanism:\n\n[code example]\n\nAnd your Redis log file should have lines in it that are similar to:\n\n[code example]"
    },
    {
      "id": "functions-in-cluster",
      "title": "Functions in cluster",
      "role": "content",
      "text": "As noted above, Redis automatically handles propagation of loaded functions to replicas.\nIn a Redis Cluster, it is also necessary to load functions to all cluster nodes. This is not handled automatically by Redis Cluster, and needs to be handled by the cluster administrator (like module loading, configuration setting, etc.).\n\nAs one of the goals of functions is to live separately from the client application, this should not be part of the Redis client library responsibilities. Instead, `redis-cli --cluster-only-masters --cluster call host:port FUNCTION LOAD ...` can be used to execute the load command on all master nodes.\n\nAlso, note that `redis-cli --cluster add-node` automatically takes care to propagate the loaded functions from one of the existing nodes to the new node."
    },
    {
      "id": "functions-and-ephemeral-redis-instances",
      "title": "Functions and ephemeral Redis instances",
      "role": "content",
      "text": "In some cases there may be a need to start a fresh Redis server with a set of functions pre-loaded. Common reasons for that could be:\n\n* Starting Redis in a new environment\n* Re-starting an ephemeral (cache-only) Redis, that uses functions\n\nIn such cases, we need to make sure that the pre-loaded functions are available before Redis accepts inbound user connections and commands.\n\nTo do that, it is possible to use `redis-cli --functions-rdb` to extract the functions from an existing server. This generates an RDB file that can be loaded by Redis at startup."
    },
    {
      "id": "function-flags",
      "title": "Function flags",
      "role": "content",
      "text": "Redis needs to have some information about how a function is going to behave when executed, in order to properly enforce resource usage policies and maintain data consistency.\n\nFor example, Redis needs to know that a certain function is read-only before permitting it to execute using [`FCALL_RO`](https://redis.io/docs/latest/commands/fcall_ro) on a read-only replica.\n\nBy default, Redis assumes that all functions may perform arbitrary read or write operations. Function Flags make it possible to declare more specific function behavior at the time of registration. Let's see how this works.\n\nIn our previous example, we defined two functions that only read data. We can try executing them using [`FCALL_RO`](https://redis.io/docs/latest/commands/fcall_ro) against a read-only replica.\n\n[code example]\n\nRedis returns this error because a function can, in theory, perform both read and write operations on the database.\nAs a safeguard and by default, Redis assumes that the function does both, so it blocks its execution.\nThe server will reply with this error in the following cases:\n\n1. Executing a function with [`FCALL`](https://redis.io/docs/latest/commands/fcall) against a read-only replica.\n2. Using [`FCALL_RO`](https://redis.io/docs/latest/commands/fcall_ro) to execute a function.\n3. A disk error was detected (Redis is unable to persist so it rejects writes).\n\nIn these cases, you can add the `no-writes` flag to the function's registration, disable the safeguard and allow them to run.\nTo register a function with flags use the [named arguments](https://redis.io/docs/latest/develop/programmability/lua-api#redis.register_function_named_args) variant of `redis.register_function`.\n\nThe updated registration code snippet from the library looks like this:\n\n[code example]\n\nOnce we've replaced the library, Redis allows running both `my_hgetall` and `my_hlastmodified` with [`FCALL_RO`](https://redis.io/docs/latest/commands/fcall_ro) against a read-only replica:\n\n[code example]\n\nFor the complete documentation flags, please refer to [Script flags](https://redis.io/docs/latest/develop/programmability/lua-api#script_flags)."
    }
  ],
  "examples": [
    {
      "id": "loading-libraries-and-functions-ex0",
      "language": "plaintext",
      "code": "#!<engine name> name=<library name>",
      "section_id": "loading-libraries-and-functions"
    },
    {
      "id": "loading-libraries-and-functions-ex1",
      "language": "plaintext",
      "code": "redis> FUNCTION LOAD \"#!lua name=mylib\\n\"\n(error) ERR No functions registered",
      "section_id": "loading-libraries-and-functions"
    },
    {
      "id": "loading-libraries-and-functions-ex2",
      "language": "lua",
      "code": "#!lua name=mylib\nredis.register_function(\n  'knockknock',\n  function() return 'Who\\'s there?' end\n)",
      "section_id": "loading-libraries-and-functions"
    },
    {
      "id": "loading-libraries-and-functions-ex3",
      "language": "plaintext",
      "code": "redis> FUNCTION LOAD \"#!lua name=mylib\\nredis.register_function('knockknock', function() return 'Who\\\\'s there?' end)\"\nmylib\nredis> FCALL knockknock 0\n\"Who's there?\"",
      "section_id": "loading-libraries-and-functions"
    },
    {
      "id": "input-keys-and-regular-arguments-ex0",
      "language": "lua",
      "code": "#!lua name=mylib\n\nlocal function my_hset(keys, args)\n  local hash = keys[1]\n  local time = redis.call('TIME')[1]\n  return redis.call('HSET', hash, '_last_modified_', time, unpack(args))\nend\n\nredis.register_function('my_hset', my_hset)",
      "section_id": "input-keys-and-regular-arguments"
    },
    {
      "id": "input-keys-and-regular-arguments-ex1",
      "language": "bash",
      "code": "$ cat mylib.lua | redis-cli -x FUNCTION LOAD REPLACE",
      "section_id": "input-keys-and-regular-arguments"
    },
    {
      "id": "input-keys-and-regular-arguments-ex2",
      "language": "plaintext",
      "code": "redis> FCALL my_hset 1 myhash myfield \"some value\" another_field \"another value\"\n(integer) 3\nredis> HGETALL myhash\n1) \"_last_modified_\"\n2) \"1640772721\"\n3) \"myfield\"\n4) \"some value\"\n5) \"another_field\"\n6) \"another value\"",
      "section_id": "input-keys-and-regular-arguments"
    },
    {
      "id": "expanding-the-library-ex0",
      "language": "lua",
      "code": "#!lua name=mylib\n\nlocal function my_hset(keys, args)\n  local hash = keys[1]\n  local time = redis.call('TIME')[1]\n  return redis.call('HSET', hash, '_last_modified_', time, unpack(args))\nend\n\nlocal function my_hgetall(keys, args)\n  redis.setresp(3)\n  local hash = keys[1]\n  local res = redis.call('HGETALL', hash)\n  res['map']['_last_modified_'] = nil\n  return res\nend\n\nlocal function my_hlastmodified(keys, args)\n  local hash = keys[1]\n  return redis.call('HGET', hash, '_last_modified_')\nend\n\nredis.register_function('my_hset', my_hset)\nredis.register_function('my_hgetall', my_hgetall)\nredis.register_function('my_hlastmodified', my_hlastmodified)",
      "section_id": "expanding-the-library"
    },
    {
      "id": "expanding-the-library-ex1",
      "language": "bash",
      "code": "$ cat mylib.lua | redis-cli -x FUNCTION LOAD REPLACE",
      "section_id": "expanding-the-library"
    },
    {
      "id": "expanding-the-library-ex2",
      "language": "plaintext",
      "code": "redis> FCALL my_hgetall 1 myhash\n1) \"myfield\"\n2) \"some value\"\n3) \"another_field\"\n4) \"another value\"\nredis> FCALL my_hlastmodified 1 myhash\n\"1640772721\"",
      "section_id": "expanding-the-library"
    },
    {
      "id": "expanding-the-library-ex3",
      "language": "plaintext",
      "code": "redis> FUNCTION LIST\n1) 1) \"library_name\"\n   2) \"mylib\"\n   3) \"engine\"\n   4) \"LUA\"\n   5) \"functions\"\n   6) 1) 1) \"name\"\n         2) \"my_hset\"\n         3) \"description\"\n         4) (nil)\n         5) \"flags\"\n         6) (empty array)\n      2) 1) \"name\"\n         2) \"my_hgetall\"\n         3) \"description\"\n         4) (nil)\n         5) \"flags\"\n         6) (empty array)\n      3) 1) \"name\"\n         2) \"my_hlastmodified\"\n         3) \"description\"\n         4) (nil)\n         5) \"flags\"\n         6) (empty array)",
      "section_id": "expanding-the-library"
    },
    {
      "id": "reusing-code-in-the-library-ex0",
      "language": "lua",
      "code": "#!lua name=mylib\n\nlocal function check_keys(keys)\n  local error = nil\n  local nkeys = table.getn(keys)\n  if nkeys == 0 then\n    error = 'Hash key name not provided'\n  elseif nkeys > 1 then\n    error = 'Only one key name is allowed'\n  end\n\n  if error ~= nil then\n    redis.log(redis.LOG_WARNING, error);\n    return redis.error_reply(error)\n  end\n  return nil\nend\n\nlocal function my_hset(keys, args)\n  local error = check_keys(keys)\n  if error ~= nil then\n    return error\n  end\n\n  local hash = keys[1]\n  local time = redis.call('TIME')[1]\n  return redis.call('HSET', hash, '_last_modified_', time, unpack(args))\nend\n\nlocal function my_hgetall(keys, args)\n  local error = check_keys(keys)\n  if error ~= nil then\n    return error\n  end\n\n  redis.setresp(3)\n  local hash = keys[1]\n  local res = redis.call('HGETALL', hash)\n  res['map']['_last_modified_'] = nil\n  return res\nend\n\nlocal function my_hlastmodified(keys, args)\n  local error = check_keys(keys)\n  if error ~= nil then\n    return error\n  end\n\n  local hash = keys[1]\n  return redis.call('HGET', keys[1], '_last_modified_')\nend\n\nredis.register_function('my_hset', my_hset)\nredis.register_function('my_hgetall', my_hgetall)\nredis.register_function('my_hlastmodified', my_hlastmodified)",
      "section_id": "reusing-code-in-the-library"
    },
    {
      "id": "reusing-code-in-the-library-ex1",
      "language": "plaintext",
      "code": "127.0.0.1:6379> FCALL my_hset 0 myhash nope nope\n(error) Hash key name not provided\n127.0.0.1:6379> FCALL my_hgetall 2 myhash anotherone\n(error) Only one key name is allowed",
      "section_id": "reusing-code-in-the-library"
    },
    {
      "id": "reusing-code-in-the-library-ex2",
      "language": "plaintext",
      "code": "...\n20075:M 1 Jan 2022 16:53:57.688 # Hash key name not provided\n20075:M 1 Jan 2022 16:54:01.309 # Only one key name is allowed",
      "section_id": "reusing-code-in-the-library"
    },
    {
      "id": "function-flags-ex0",
      "language": "plaintext",
      "code": "redis > FCALL_RO my_hgetall 1 myhash\n(error) ERR Can not execute a function with write flag using fcall_ro.",
      "section_id": "function-flags"
    },
    {
      "id": "function-flags-ex1",
      "language": "lua",
      "code": "redis.register_function('my_hset', my_hset)\nredis.register_function{\n  function_name='my_hgetall',\n  callback=my_hgetall,\n  flags={ 'no-writes' }\n}\nredis.register_function{\n  function_name='my_hlastmodified',\n  callback=my_hlastmodified,\n  flags={ 'no-writes' }\n}",
      "section_id": "function-flags"
    },
    {
      "id": "function-flags-ex2",
      "language": "plaintext",
      "code": "redis> FCALL_RO my_hgetall 1 myhash\n1) \"myfield\"\n2) \"some value\"\n3) \"another_field\"\n4) \"another value\"\nredis> FCALL_RO my_hlastmodified 1 myhash\n\"1640772721\"",
      "section_id": "function-flags"
    }
  ]
}
