{
  "id": "programmability",
  "title": "Redis programmability",
  "url": "https://un5pn9hmggug.julianrbryant.com/docs/latest/develop/programmability/",
  "summary": "Extending Redis with Lua and Redis Functions",
  "tags": [
    "docs",
    "develop",
    "stack",
    "oss",
    "rs",
    "rc",
    "oss",
    "kubernetes",
    "clients"
  ],
  "last_updated": "2026-04-01T08:10:08-05:00",
  "children": [
    {
      "id": "functions-intro",
      "summary": "Scripting with Redis 7 and beyond",
      "title": "Redis functions",
      "url": "https://un5pn9hmggug.julianrbryant.com/docs/latest/develop/programmability/functions-intro/"
    },
    {
      "id": "eval-intro",
      "summary": "Executing Lua in Redis",
      "title": "Scripting with Lua",
      "url": "https://un5pn9hmggug.julianrbryant.com/docs/latest/develop/programmability/eval-intro/"
    },
    {
      "id": "lua-api",
      "summary": "Executing Lua in Redis",
      "title": "Redis Lua API reference",
      "url": "https://un5pn9hmggug.julianrbryant.com/docs/latest/develop/programmability/lua-api/"
    },
    {
      "id": "lua-debugging",
      "summary": "How to use the built-in Lua debugger",
      "title": "Debugging Lua scripts in Redis",
      "url": "https://un5pn9hmggug.julianrbryant.com/docs/latest/develop/programmability/lua-debugging/"
    }
  ],
  "page_type": "content",
  "content_hash": "107bdcfbe758f4d3c3160b933a42a6efc7193e66c57362052473968c9708b812",
  "sections": [
    {
      "id": "overview",
      "title": "Overview",
      "role": "overview",
      "text": "Redis provides a programming interface that lets you execute custom scripts on the server itself. In Redis 7 and beyond, you can use [Redis Functions]() to manage and run your scripts. In Redis 6.2 and below, you use [Lua scripting with the EVAL command]() to program the server."
    },
    {
      "id": "background",
      "title": "Background",
      "role": "content",
      "text": "Redis is, by [definition](https://github.com/redis/redis/blob/unstable/MANIFESTO#L7), a _\"domain-specific language for abstract data types\"_.\nThe language that Redis speaks consists of its [commands]().\nMost the commands specialize at manipulating core [data types]() in different ways.\nIn many cases, these commands provide all the functionality that a developer requires for managing application data in Redis.\n\nThe term **programmability** in Redis means having the ability to execute arbitrary user-defined logic by the server.\nWe refer to such pieces of logic as **scripts**.\nIn our case, scripts enable processing the data where it lives, a.k.a _data locality_.\nFurthermore, the responsible embedding of programmatic workflows in the Redis server can help in reducing network traffic and improving overall performance.\nDevelopers can use this capability for implementing robust, application-specific APIs.\nSuch APIs can encapsulate business logic and maintain a data model across multiple keys and different data structures.\n\nUser scripts are executed in Redis by an embedded, sandboxed scripting engine.\nPresently, Redis supports a single scripting engine, the [Lua 5.1](https://un5gmtkzgjttpm6gt32g.julianrbryant.com/) interpreter.\n\nPlease refer to the [Redis Lua API Reference]() page for complete documentation."
    },
    {
      "id": "running-scripts",
      "title": "Running scripts",
      "role": "content",
      "text": "Redis provides two means for running scripts.\n\nFirstly, and ever since Redis 2.6.0, the [`EVAL`]() command enables running server-side scripts.\nEval scripts provide a quick and straightforward way to have Redis run your scripts ad-hoc.\nHowever, using them means that the scripted logic is a part of your application (not an extension of the Redis server).\nEvery applicative instance that runs a script must have the script's source code readily available for loading at any time.\nThat is because scripts are only cached by the server and are volatile.\nAs your application grows, this approach can become harder to develop and maintain.\n\nSecondly, added in v7.0, Redis Functions are essentially scripts that are first-class database elements.\nAs such, functions decouple scripting from application logic and enable independent development, testing, and deployment of scripts.\nTo use functions, they need to be loaded first, and then they are available for use by all connected clients.\nIn this case, loading a function to the database becomes an administrative deployment task (such as loading a Redis module, for example), which separates the script from the application.\n\nPlease refer to the following pages for more information:\n\n* [Redis Eval Scripts]()\n* [Redis Functions]()\n\nWhen running a script or a function, Redis guarantees its atomic execution.\nThe script's execution blocks all server activities during its entire time, similarly to the semantics of [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 script apply to all connected clients at all times.\n\nNote that the potential downside of this blocking approach is that executing slow scripts is not a good idea.\nIt is not hard to create fast scripts because scripting's overhead is very low.\nHowever, if you intend to use a slow script in your application, be aware that all other clients are blocked and can't execute any command while it is running."
    },
    {
      "id": "read-only-scripts",
      "title": "Read-only scripts",
      "role": "content",
      "text": "A read-only script is a script that only executes commands that don't modify any keys within Redis.\nRead-only scripts can be executed either by adding the `no-writes` [flag]() to the script or by executing the script with one of the read-only script command variants: [`EVAL_RO`](), [`EVALSHA_RO`](), or [`FCALL_RO`]().\nThey have the following properties:\n\n* They can always be executed on replicas.\n* They can always be killed by the [`SCRIPT KILL`]() command. \n* They never fail with OOM error when redis is over the memory limit.\n* They are not blocked during write pauses, such as those that occur during coordinated failovers.\n* They cannot execute any command that may modify the data set.\n* Currently [`PUBLISH`](), [`SPUBLISH`]() and [`PFCOUNT`]() are also considered write commands in scripts, because they could attempt to propagate commands to replicas and AOF file.\n\nIn addition to the benefits provided by all read-only scripts, the read-only script commands have the following advantages:\n\n* They can be used to configure an ACL user to only be able to execute read-only scripts.\n* Many clients also better support routing the read-only script commands to replicas for applications that want to use replicas for read scaling.\n\n#### Read-only script history\n\nRead-only scripts and read-only script commands were introduced in Redis 7.0\n\n* Before Redis 7.0.1 [`PUBLISH`](), [`SPUBLISH`]() and [`PFCOUNT`]() were not considered write commands in scripts\n* Before Redis 7.0.1 the `no-writes` [flag]() did not imply `allow-oom`\n* Before Redis 7.0.1 the `no-writes` flag did not permit the script to run during write pauses.\n\n\nThe recommended approach is to use the standard scripting commands with the `no-writes` flag unless you need one of the previously mentioned features."
    },
    {
      "id": "sandboxed-script-context",
      "title": "Sandboxed script context",
      "role": "content",
      "text": "Redis places the engine that executes user scripts inside a sandbox.\nThe sandbox attempts to prevent accidental misuse and reduce potential threats from the server's environment.\n\nScripts should never try to access the Redis server's underlying host systems, such as the file system, network, or attempt to perform any other system call other than those supported by the API.\n\nScripts should operate solely on data stored in Redis and data provided as arguments to their execution."
    },
    {
      "id": "maximum-execution-time",
      "title": "Maximum execution time",
      "role": "content",
      "text": "Scripts are subject to a maximum execution time (set by default to five seconds).\nThis default timeout is enormous since a script usually runs in less than a millisecond.\nThe limit is in place to handle accidental infinite loops created during development.\n\nIt is possible to modify the maximum time a script can be executed with millisecond precision,\neither via `redis.conf` or by using the [`CONFIG SET`]() command.\nThe configuration parameter affecting max execution time is called `busy-reply-threshold`.\n\nWhen a script reaches the timeout threshold, it isn't terminated by Redis automatically.\nDoing so would violate the contract between Redis and the scripting engine that ensures that scripts are atomic.\nInterrupting the execution of a script has the potential of leaving the dataset with half-written changes.\n\nTherefore, when a script executes longer than the configured timeout, the following happens:\n\n* Redis logs that a script is running for too long.\n* It starts accepting commands again from other clients but will reply with a BUSY error to all the clients sending normal commands. The only commands allowed in this state are [`SCRIPT KILL`](), [`FUNCTION KILL`](), and `SHUTDOWN NOSAVE`.\n* It is possible to terminate a script that only executes read-only commands using the [`SCRIPT KILL`]() and [`FUNCTION KILL`]() commands. These commands do not violate the scripting semantic as no data was written to the dataset by the script yet.\n* If the script had already performed even a single write operation, the only command allowed is `SHUTDOWN NOSAVE` that stops the server without saving the current data set on disk (basically, the server is aborted)."
    }
  ],
  "examples": []
}
