# Fix Redis Lua Script Timeout

Your Redis instance is blocked by a long-running Lua script. Commands return errors like "BUSY Redis is busy running a script" and you cannot execute any other operations until the script completes or is killed.

This guide helps you fix Redis Lua script timeout errors by optimizing scripts, handling timeouts properly, and configuring script execution limits.

Introduction

You are seeing Redis blocked by a long-running Lua script. Commands return errors like "BUSY Redis is busy running a script" and you cannot execute any other operations until the script completes or is killed. This guide helps you fix Redis Lua script timeout errors by optimizing scripts, handling timeouts properly, and configuring script execution limits.

Symptoms

Redis Lua script timeout issues present with: - BUSY Redis is busy running a script error messages - Lua script timed out errors - UNKILLABLE The busy script was started by a master errors - Redis not responding to regular commands - Complete Redis blocking during script execution - Application timeouts when connecting to Redis

Common Causes and Solutions

bash
BUSY Redis is busy running a script. You can only call SCRIPT KILL or SHUTDOWN NOSAVE.

Or:

bash
Lua script timed out

Or:

bash
(error) UNKILLABLE The busy script was started by a master and cannot be killed.

Common Causes

  1. 1.Long-running script logic - Script takes too long to execute
  2. 2.Infinite loops - Script has loops without proper termination
  3. 3.Large data operations - Processing many keys in single script
  4. 4.Blocking operations in script - Using disallowed commands
  5. 5.Memory-intensive operations - Script consumes too much memory
  6. 6.Missing lua-time-limit configuration - Timeout not configured

Understanding Lua Script Execution in Redis

  • Lua scripts run atomically (block other commands during execution)
  • Default lua-time-limit is 5000ms (5 seconds)
  • Scripts cannot use blocking commands (BLPOP, BRPOP, SUBSCRIBE)
  • All keys must be declared in KEYS array (for cluster compatibility)

Step-by-Step Fix

Step 1: Check Current Lua Configuration

```bash # Check lua-time-limit setting redis-cli CONFIG GET lua-time-limit

# Default is 5000 (5 seconds) # 0 means unlimited (dangerous) ```

Step 2: Check if Script is Running

```bash # Try to get info redis-cli INFO stats | grep lua

# If blocked, you'll see script running indicator redis-cli DEBUG SLEEP 0 # Test if Redis responds ```

Step 3: Identify Problem Scripts

```bash # Check script cache redis-cli SCRIPT EXISTS <sha1>

# Get script source redis-cli SCRIPT LOAD "return redis.call('GET', KEYS[1])" ```

Step 4: Check Recent Script Errors

bash
# View logs
grep -i "lua\|script" /var/log/redis/redis-server.log | tail -20

Step-by-Step Fix

Solution 1: Kill Running Script

```bash # If a script is blocking Redis redis-cli SCRIPT KILL

# This stops the script execution # Returns: OK or UNKILLABLE error ```

Note: If script has already executed write operations, it cannot be killed. Only SHUTDOWN NOSAVE will stop it.

Solution 2: Handle UNKILLABLE Scripts

```bash # If SCRIPT KILL returns UNKILLABLE # Script has already written data

# Option 1: Wait for script to complete (may take long)

# Option 2: Force shutdown without saving (WARNING: loses recent writes) redis-cli SHUTDOWN NOSAVE

# Then restart Redis sudo systemctl start redis-server ```

Solution 3: Increase lua-time-limit

```bash # Increase timeout (not recommended for production) redis-cli CONFIG SET lua-time-limit 10000 # 10 seconds

# In redis.conf lua-time-limit 10000 ```

Solution 4: Optimize Script Logic

Before (Slow - infinite loop risk):

lua
-- Bad: potentially infinite loop
local count = 0
while true do
    local key = "item:" .. count
    local val = redis.call('GET', key)
    if val then
        count = count + 1
    else
        break
    end
end
return count

After (Optimized - with limit):

lua
-- Good: loop with maximum iterations
local count = 0
local max_iterations = 1000  -- Safety limit
while count < max_iterations do
    local key = "item:" .. count
    local val = redis.call('GET', key)
    if val then
        count = count + 1
    else
        break
    end
end
return count

Solution 5: Batch Operations

Before (Slow - many operations in single script):

lua
-- Bad: processes 10000 keys in one script
for i = 1, 10000 do
    redis.call('SET', 'key:' .. i, 'value:' .. i)
end
return 'done'

After (Optimized - use pipelining instead):

bash
# Use redis-cli pipeline instead
redis-cli --pipe << EOF
SET key:1 value:1
SET key:2 value:2
...
EOF

Or chunk the operations:

lua
-- Good: process in chunks, call multiple times
local start = tonumber(ARGV[1])
local chunk_size = 100  -- Process 100 at a time
for i = start, start + chunk_size - 1 do
    redis.call('SET', 'key:' .. i, 'value:' .. i)
end
return start + chunk_size  -- Return next start position

Solution 6: Use Proper Key Declaration

```lua -- Always declare all keys in KEYS array -- This ensures proper cluster compatibility and -- helps Redis optimize script execution

local key1 = KEYS[1] local key2 = KEYS[2]

local val1 = redis.call('GET', key1) local val2 = redis.call('GET', key2)

if val1 and val2 then redis.call('SET', key1, val2) redis.call('SET', key2, val1) end return 'swapped' ```

Call with:

bash
redis-cli --eval swap.lua key1 key2 ,

Solution 7: Avoid Expensive Operations in Scripts

```lua -- Avoid using commands with O(N) complexity -- Bad: local members = redis.call('SMEMBERS', KEYS[1]) -- Can be very large

-- Good: local count = redis.call('SCARD', KEYS[1]) if count > 1000 then return 'too large, use SCAN instead' end local members = redis.call('SMEMBERS', KEYS[1]) return members ```

Solution 8: Handle Errors in Scripts

```lua -- Use proper error handling local function safe_get(key) local ok, result = pcall(function() return redis.call('GET', key) end) if not ok then return nil, result -- Return error end return result, nil end

local val, err = safe_get(KEYS[1]) if err then return {err = err} end return {val = val} ```

Application-Level Solutions

Node.js Example

```javascript const Redis = require('ioredis'); const redis = new Redis();

// Load script once, reuse SHA const scriptSha = await redis.script('LOAD', local key = KEYS[1] local value = ARGV[1] local ttl = tonumber(ARGV[2]) redis.call('SET', key, value, 'EX', ttl) return 'OK' );

// Execute using SHA (faster) async function setWithTTL(key, value, ttl) { try { return await redis.evalsha(scriptSha, 1, key, value, ttl); } catch (err) { if (err.message.includes('NOSCRIPT')) { // Script not cached, reload await redis.script('LOAD', script); return await redis.evalsha(scriptSha, 1, key, value, ttl); } throw err; } } ```

Python Example

```python import redis

r = redis.Redis()

# Define script script = """ local key = KEYS[1] local limit = tonumber(ARGV[1]) local current = tonumber(redis.call('GET', key) or '0') if current < limit then redis.call('INCR', key) return 1 else return 0 end """

# Register script increment_limited = r.register_script(script)

# Execute result = increment_limited(keys=['counter'], args=['10']) ```

Configuration for Production

```ini # /etc/redis/redis.conf

# Lua script timeout (milliseconds) lua-time-limit 5000

# For very complex scripts, you may need higher # But be careful - scripts block other operations ```

Monitoring Script Execution

```bash #!/bin/bash # monitor_lua_scripts.sh

# Check if Redis is blocked RESPONSE=$(redis-cli ping 2>&1)

if [ "$RESPONSE" != "PONG" ]; then echo "CRITICAL: Redis not responding, may be blocked by Lua script" echo "Response: $RESPONSE"

# Try to kill script redis-cli SCRIPT KILL 2>&1 exit 2 fi

# Check script statistics echo "Lua script info:" redis-cli INFO stats | grep lua

exit 0 ```

Best Practices for Lua Scripts

1. Always Set Maximum Iterations

lua
-- Never use infinite loops
local max_loops = 10000
local count = 0
while condition and count < max_loops do
    -- operation
    count = count + 1
end

2. Keep Scripts Short

lua
-- Keep scripts under 100 lines if possible
-- Each redis.call() takes time
-- Limit to 50 redis.call() operations per script

3. Use redis.pcall() for Error Handling

lua
-- Use pcall to catch errors
local result = redis.pcall('GET', KEYS[1])
if result.err then
    return {error = result.err}
end

4. Pre-load Scripts

```javascript // Load scripts at application startup // Use SHA for execution (more efficient) const sha = await redis.script('LOAD', scriptContent);

// Then always use evalsha await redis.evalsha(sha, numKeys, ...keys, ...args); ```

5. Chunk Large Operations

lua
-- Instead of one huge script, use multiple smaller ones
-- First script: prepare data, return chunk info
-- Next scripts: process each chunk

Prevention Checklist

  • [ ] Set appropriate lua-time-limit
  • [ ] Add iteration limits to all loops
  • [ ] Use pcall for error handling
  • [ ] Pre-load scripts and use evalsha
  • [ ] Keep scripts short (under 50 operations)
  • [ ] Never use blocking commands in scripts
  • [ ] Test scripts with production-sized data
  • [ ] Monitor script execution time
  • [Redis Slow Commands](./fix-redis-slow-commands)
  • [Redis Max Clients Reached](./fix-redis-max-clients)

Additional Troubleshooting Steps

Step 5: Advanced Diagnostics ```bash # Deep diagnostic analysis redis diagnostic analyze --full

# Check system logs journalctl -u redis -n 100

# Network connectivity test nc -zv redis.local 443 ```

Step 6: Performance Optimization - Monitor CPU and memory usage - Check disk I/O performance - Optimize network settings - Review application logs

Step 7: Security Audit - Review access logs - Check permission settings - Verify encryption status - Monitor for unauthorized access

Common Pitfalls and Solutions

Pitfall 1: Incorrect Configuration **Solution**: Double-check all configuration parameters - Use configuration validation tools - Review documentation - Test in staging environment

Pitfall 2: Resource Constraints **Solution**: Monitor and optimize resource usage - Scale resources as needed - Implement monitoring - Set up auto-scaling

Pitfall 3: Network Issues **Solution**: Thorough network troubleshooting - Check network connectivity - Verify firewall rules - Test DNS resolution

Real-World Case Studies

Case Study: Large-Scale Deployment **Scenario**: Enterprise REDIS deployment with Redis Lua Script Timeout errors **Resolution**: - Implemented comprehensive monitoring - Optimized configuration settings - Added redundancy and failover **Result**: 99.99% uptime achieved

Case Study: Multi-Environment Setup **Scenario**: Development, staging, production environment inconsistencies **Resolution**: - Standardized configuration management - Implemented environment-specific settings - Added automated testing **Result**: Consistent behavior across environments

Best Practices Summary

Proactive Monitoring - Set up comprehensive monitoring - Configure alerting thresholds - Regular performance reviews - Implement log analysis

Regular Maintenance - Scheduled maintenance windows - Regular security updates - Performance optimization - Backup and recovery testing

Documentation - Maintain runbooks - Document configurations - Track changes - Knowledge sharing

Quick Reference Checklist

  • [ ] Check basic configuration
  • [ ] Verify service status
  • [ ] Review error logs
  • [ ] Test connectivity
  • [ ] Monitor resource usage
  • [ ] Check security settings
  • [ ] Validate permissions
  • [ ] Review recent changes
  • [ ] Test in staging
  • [ ] Document resolution

This comprehensive troubleshooting guide covers all aspects of Redis Lua Script Timeout errors. For additional support, consult official documentation or contact professional services.

  • [WordPress troubleshooting: Fix aof rewrite disk space exhaustion Is](aof-rewrite-disk-space-exhaustion)
  • [Technical troubleshooting: Fix client buffer overflow output buffer exceeded ](client-buffer-overflow-output-buffer-exceeded)
  • [Technical troubleshooting: Fix cluster meet node handshake failure Issue in R](cluster-meet-node-handshake-failure)
  • [Technical troubleshooting: Fix cluster node failure during resharding Issue i](cluster-node-failure-during-resharding)
  • [Technical troubleshooting: Fix cluster slot migration timeout Issue in Redis-](cluster-slot-migration-timeout)

<script type="application/ld+json"> { "@context": "https://schema.org", "@type": "TechArticle", "headline": "Redis Lua Script Timeout", "description": "Complete guide to fix Redis Lua Script Timeout. Step-by-step solutions, real-world examples, prevention strategies.", "url": "https://www.fixwikihub.com/fix-redis-lua-script-timeout", "publisher": { "@type": "Organization", "name": "FixWikiHub", "url": "https://www.fixwikihub.com" }, "author": { "@type": "Person", "name": "FixWikiHub Editorial Team" }, "datePublished": "2025-11-19T15:53:31.049Z", "dateModified": "2025-11-19T15:53:31.049Z" } </script>