Skip to main content
Use FCALL to invoke a function from a library loaded with FUNCTION LOAD. <numkeys> tells the server how many of the arguments that follow are key names. Those keys reach the function in KEYS and every remaining argument in ARGV. Passing key names as keys instead of hardcoding them in the function body matters, because Redis uses that list for routing and access checks. The function runs on the server as a single atomic step, so a sequence of reads and writes that would otherwise need several round trips and a transaction becomes one command. Use FCALL_RO when the function only reads. Functions are the successor to EVAL scripts: they are named, registered once as part of a library, and persisted with the dataset instead of being sent or looked up by digest on every call. Upstash runs a function under the global lock by default, since the engine cannot know in advance which keys it will touch. Registering the function with the allow-key-locking flag makes the call lock the hash tag of each key passed in the key list, so calls that work on disjoint hash tags run in parallel:
Unlike Lua scripts, where the flag goes on the library shebang, this flag is set per registered function. With it set, every key the function touches must be passed as a key in the FCALL call or share a valid hash tag with an already locked key. Commands that need database-wide access, such as FLUSHDB, are rejected. See Key-Based Locking for the full rules.
Pass every key the function touches in the key list when possible, even when it runs under the global lock. Upstash keeps idle entries on disk: declared keys are loaded before the function starts and the lock is released during that read. A same-tag dynamic key is allowed with allow-key-locking, but it is read from disk with the lock held. This stalls commands using the same hash tag, or the whole database when the function uses the global lock. See Dynamic Keys and Latency.

Syntax

Arguments

Important points

  • numkeys must equal the number of key arguments that immediately follow it; remaining arguments are available to the script or function as ordinary arguments.
  • The function takes the global lock unless it was registered with the allow-key-locking flag, in which case it locks the hash tag of each key passed in the key list and any matching Search indexes. See Key-Based Locking.
  • Pass every key the function touches in the key list when possible. With allow-key-locking, a dynamic key is accepted only when its hash tag is already locked, and a cold dynamic key is loaded with that lock held. See Dynamic Keys and Latency.

Reply conversion

redis.setresp() and the RESP2 and RESP3 conversions applied to redis.call replies work exactly as they do for EVAL.

Response

The reply reports the result of the operation. Error replies have the same shape in RESP2 and RESP3 and are surfaced as exceptions by the SDKs below.
Client libraries often decode bulk strings, maps, sets, and numeric strings into language-native values. The table describes the Redis wire reply.

Examples

TCP examples use the TLS REDIS_URL from the Upstash console. REST examples use UPSTASH_REDIS_REST_URL and UPSTASH_REDIS_REST_TOKEN.
This command is not supported yet in upstash_redis.