Execute Lua scripts efficiently with automatic SHA-1 caching
The Script and ScriptRO classes allow you to execute Lua scripts efficiently by using Redis’s EVALSHA command, which caches scripts on the server for faster execution.
Deprecated: This property is initialized asynchronously and may be an empty string immediately after construction. It’s exposed for backwards compatibility only.
The SHA-1 hash of the script.
const myScript = redis.createScript('return ARGV[1];');// Wait for initialization before accessingawait new Promise(resolve => setTimeout(resolve, 100));console.log(myScript.sha1); // SHA-1 hash
The ScriptRO class is identical to Script but uses read-only commands (EVAL_RO and EVALSHA_RO). This is useful for scripts that only read data and can be executed on read replicas.
const incrementCounter = redis.createScript<number>( ` local count = redis.call("INCR", KEYS[1]) local ttl = redis.call("TTL", KEYS[1]) if ttl == -1 then redis.call("EXPIRE", KEYS[1], ARGV[1]) end return count `);// Increment counter and set 1 hour expiry if not setconst count = await incrementCounter.exec( ['page:views:homepage'], ['3600']);
const setIfHigher = redis.createScript<number>( ` local current = redis.call("GET", KEYS[1]) local new = tonumber(ARGV[1]) if current == false or tonumber(current) < new then redis.call("SET", KEYS[1], new) return new end return tonumber(current) `);const highScore = await setIfHigher.exec( ['user:123:highscore'], ['1500']);
const checkRateLimit = redis.createScript<[number, number]>( ` local key = KEYS[1] local limit = tonumber(ARGV[1]) local window = tonumber(ARGV[2]) local current = redis.call("INCR", key) if current == 1 then redis.call("EXPIRE", key, window) end local ttl = redis.call("TTL", key) return {current, ttl} `);const [requests, ttl] = await checkRateLimit.exec( ['ratelimit:user:123'], ['100', '60'] // 100 requests per 60 seconds);if (requests > 100) { throw new Error(`Rate limit exceeded. Try again in ${ttl} seconds.`);}
// Return type is inferredconst script = redis.createScript<{ count: number; timestamp: number }>( ` local count = redis.call("INCR", KEYS[1]) local time = redis.call("TIME") return {count, time[1]} `);const result = await script.exec(['counter'], []);// result is typed as { count: number; timestamp: number }
/** * Atomically increment a counter and maintain top N leaderboard * * @param KEYS[1] - Counter key * @param KEYS[2] - Sorted set key for leaderboard * @param ARGV[1] - User ID * @param ARGV[2] - Maximum leaderboard size */const updateLeaderboard = redis.createScript<number>( `...`);