# EVAL

> Run a Lua script on the server, atomically.

URL: https://docs.hotkv.com/commands/eval/

```
EVAL script numkeys [key [key ...]] [arg [arg ...]]
```

- Group: Scripting and functions
- Complexity: Depends on the script
- HotKV Cloud: all plans
- On-Premise: no license needed

`EVAL` runs a Lua script on the server. The script runs atomically: no other
client's command runs while it executes, so you can read, decide and write in
one step without a transaction. Inside the script, `KEYS` holds the
`numkeys` key names that follow `numkeys`, and `ARGV` holds the remaining
arguments. Call commands with `redis.call()` (which raises an error on an
error reply) or `redis.pcall()` (which returns the error as a value); the same
API is also available as `server`.

Pass every key the script touches in `KEYS`, so that ACL key rules and cluster
routing can see them. A script without a shebang line may use keys of several
slots, as in Redis 7, though each command it runs must still use keys of one
slot. See [Lua scripting](https://docs.hotkv.com/develop/lua-scripting/index.md) for the full scripting
guide.

The script is compiled and cached under the SHA1 digest of its text, so you
can run it again with [EVALSHA](https://docs.hotkv.com/commands/evalsha/index.md) without resending it.

### Script flags

A script may start with a shebang line that declares flags, for example
`#!lua flags=no-writes,allow-oom`:

| Flag | Effect |
| --- | --- |
| `no-writes` | The script may not write. It can run on read-only replicas and with [EVAL_RO](https://docs.hotkv.com/commands/eval_ro/index.md). |
| `allow-oom` | The script may run when the server is over `maxmemory`. |
| `allow-stale` | The script may run on a replica whose link to its primary is down. |
| `no-cluster` | The script refuses to run on a cluster node. |
| `allow-cross-slot-keys` | In a cluster, the script may access keys of several slots, if all of them are on the node that runs it. |

A script with a shebang line is checked against its flags before it runs (for
example, one that may write is refused on a read-only replica). A script
without one is checked as it runs each command.

## Return value

The script's return value, converted to RESP:

| Lua value | RESP2 | RESP3 |
| --- | --- | --- |
| Number | Integer (fractional part dropped) | Integer |
| String | Bulk string | Bulk string |
| Table with array items | Array (stops at the first nil) | Array |
| `{ok = "..."}` or `redis.status_reply()` | Simple string | Simple string |
| `{err = "..."}` or `redis.error_reply()` | Error | Error |
| `false` or nil | Nil bulk string | Null |
| `true` | Integer `1` | Integer `1` |

With `redis.setresp(3)` the script receives RESP3 replies from its commands,
and maps, sets, doubles and booleans it returns are sent as such to RESP3
clients.

Errors:

- `ERR Number of keys can't be greater than number of args` and
  `ERR Number of keys can't be negative` for a bad `numkeys`.
- `ERR Error compiling script (new function): ...` for a script that does not
  compile.
- `ERR Write commands are not allowed from read-only scripts.` when a
  `no-writes` script writes.
- `BUSY HotKV is busy running a script. You can only call SCRIPT KILL or SHUTDOWN NOSAVE.`
  for other clients while a script has run longer than `busy-reply-threshold`.

## Examples

```
127.0.0.1:6379> EVAL "return redis.call('SET', KEYS[1], ARGV[1])" 1 greeting "hello"
OK
127.0.0.1:6379> EVAL "return redis.call('GET', KEYS[1])" 1 greeting
"hello"
127.0.0.1:6379> EVAL "return {1, 2, 'three'}" 0
1) (integer) 1
2) (integer) 2
3) "three"
127.0.0.1:6379> EVAL "return redis.call('INCRBY', KEYS[1], ARGV[1])" 1 hits 5
(integer) 5
```

## Compatibility

Same arguments, flags and replies as Redis 7 and Valkey 8. The script debugger
is not available (see [SCRIPT DEBUG](https://docs.hotkv.com/commands/script-debug/index.md)).

## See also

[EVALSHA](https://docs.hotkv.com/commands/evalsha/index.md), [EVAL_RO](https://docs.hotkv.com/commands/eval_ro/index.md),
[SCRIPT LOAD](https://docs.hotkv.com/commands/script-load/index.md), [SCRIPT KILL](https://docs.hotkv.com/commands/script-kill/index.md),
[FCALL](https://docs.hotkv.com/commands/fcall/index.md)

In a cluster: [Keys, slots and commands in a cluster](https://docs.hotkv.com/clustering/keys-and-commands/index.md#scripts-and-functions)