Documentation Index Fetch the complete documentation index at: https://mintlify.com/KevinhosUTP/Automatizacion-Lurwis/llms.txt
Use this file to discover all available pages before exploring further.
Redis provides temporary message storage to batch rapid customer messages before processing, preventing duplicate agent responses and reducing AI API calls.
Purpose
When customers send multiple messages quickly (e.g., “Hola”, “Quiero”, “Un ceviche”), the system:
Buffers messages in Redis with 30-second TTL
Waits 8 seconds after last message
Concatenates messages into single context
Processes once through AI agents
This prevents:
Duplicate/conflicting AI responses
Wasted API calls for incomplete thoughts
Poor user experience from interleaved replies
Redis Setup
Install Redis
Docker
Ubuntu/Debian
Cloud (Redis Labs)
docker run -d \
--name redis-lurwis \
-p 6379:6379 \
redis:7-alpine \
redis-server --requirepass your_password
Configure authentication
Edit /etc/redis/redis.conf (if self-hosted): requirepass your_secure_password
maxmemory 256mb
maxmemory-policy allkeys-lru
Restart Redis: sudo systemctl restart redis-server
Test connection
redis-cli -h localhost -p 6379 -a your_password
127.0.0.1:6379 > PING
PONG
127.0.0.1:6379 > SET test "hello"
OK
127.0.0.1:6379 > GET test
"hello"
Connection Configuration
n8n Credentials
n8n Redis Credential
Environment Variables
{
"id" : "LuOIeLYx2ps0SCoP" ,
"name" : "Buffer Lurwis" ,
"type" : "redis" ,
"data" : {
"host" : "localhost" ,
"port" : 6379 ,
"password" : "your_password" ,
"database" : 0 ,
"ssl" : false
}
}
Buffer Workflow
The Receptor workflow implements a three-key buffer system:
Key Structure
// Per user (phone number: 51900769907)
buffer_51900769907 → Accumulated message text
ts_51900769907 → Last message timestamp
meta_51900769907 → WhatsApp phone_number_id
Buffer Operations
Receive message
When a WhatsApp message arrives: const userId = message . from ; // "51900769907"
const messageText = message . text . body ;
Check existing buffer
// Redis GET operation
const existingBuffer = await redis . get ( `buffer_ ${ userId } ` );
if ( existingBuffer ) {
// Concatenate new message
const updatedBuffer = ` ${ existingBuffer } \n ${ messageText } ` ;
} else {
// First message
const updatedBuffer = messageText ;
}
Save buffer with TTL
// Set buffer with 30 second expiration
await redis . set ( `buffer_ ${ userId } ` , updatedBuffer , 'EX' , 30 );
// Save timestamp (also 30s)
await redis . set ( `ts_ ${ userId } ` , Date . now (). toString (), 'EX' , 30 );
// Save metadata (2 minute expiration)
await redis . set ( `meta_ ${ userId } ` , phoneNumberId , 'EX' , 120 );
Return 200 OK immediately
Respond to WhatsApp within 20 seconds: return {
statusCode: 200 ,
headers: { 'Content-Type' : 'text/plain' },
body: 'OK'
};
Processing Workflow
The Procesador workflow runs every 10 seconds to check for ready buffers:
Find active users
// Get all timestamp keys
const keys = await redis . keys ( 'ts_*' );
// Example result: ["ts_51900769907", "ts_51987654321"]
Check if buffer is ready
for ( const key of keys ) {
const timestamp = await redis . get ( key );
const timeSinceLastMessage = Date . now () - parseInt ( timestamp );
// Process if more than 8 seconds since last message
if ( timeSinceLastMessage > 8000 ) {
// Ready to process
}
}
Read and delete buffer
const userId = key . replace ( 'ts_' , '' );
// Read all data
const buffer = await redis . get ( `buffer_ ${ userId } ` );
const metadata = await redis . get ( `meta_ ${ userId } ` );
// Delete keys immediately
await redis . del ( `buffer_ ${ userId } ` );
await redis . del ( `ts_ ${ userId } ` );
await redis . del ( `meta_ ${ userId } ` );
Process concatenated messages
// Concatenate buffered messages into single text
const messagesArray = buffer . split ( ' \n ' );
const combinedMessage = messagesArray
. map ( m => m . trim ())
. filter ( m => m . length > 0 )
. join ( ' ' );
// Example:
// Input: ["Hola", "Quiero", "Un ceviche"]
// Output: "Hola Quiero Un ceviche"
// Send to AI agent as single context
processWithAgent ( combinedMessage );
TTL Configuration
Buffer TTL (30 seconds)
Timestamp TTL (30 seconds)
Metadata TTL (120 seconds)
{
"operation" : "set" ,
"key" : "{{ $json.bufferKey }}" ,
"value" : "{{ String($json.bufferContent) }}" ,
"expire" : true ,
"ttl" : 30
}
Buffer expires after 30s. Processor checks every 10s and waits 8s after last message. Maximum latency: 18 seconds.
Code Implementation
Complete buffer management code from the workflow:
// Buffer: Agregar Mensaje (Code node)
let existingBuffer = '' ;
try {
const redisResult = $input . first ()?. json ;
existingBuffer = redisResult ?. value || redisResult ?. propertyName || '' ;
} catch ( e ) {
existingBuffer = '' ;
}
const extractorData = $ ( 'Extractormensajes' ). item . json ;
const newMessage = extractorData ?. text ?. body || extractorData ?.[ 'text.body' ] || '' ;
const userId = extractorData . from ;
const updatedBuffer = existingBuffer
? ` ${ existingBuffer } \n ${ newMessage } `
: newMessage ;
const now = Date . now ();
return {
json: {
bufferKey: `buffer_ ${ userId } ` ,
timestampKey: `ts_ ${ userId } ` ,
metaKey: `meta_ ${ userId } ` ,
bufferContent: updatedBuffer ,
timestamp: now ,
userId: userId ,
idMensajero: extractorData [ 'id mensajero' ] || '' ,
profileName: extractorData . profile_name || 'Cliente' ,
messageCount: updatedBuffer . split ( ' \n ' ). length
}
};
Redis Operations Used
Operation Purpose Example SET Store buffer/timestamp/metadata SET buffer_51900 "Hola" EX 30GET Retrieve buffer for processing GET buffer_51900KEYS Find all active users KEYS ts_*DEL Remove processed buffer DEL buffer_51900TTL Check time remaining TTL buffer_51900
Memory Management
Memory Policy
Configure eviction when memory limit reached:
maxmemory 256mb
maxmemory-policy allkeys-lru
Policy options:
allkeys-lru - Evict least recently used keys (recommended)
volatile-ttl - Evict keys with shortest TTL
volatile-lru - Evict LRU keys with expiration set
Memory Usage Estimation
Typical memory per user:
Buffer key: ~100 bytes (avg message length)
Timestamp key: ~20 bytes
Metadata key: ~30 bytes
------------------------
Total per user: ~150 bytes
Capacity:
256 MB = ~1.7 million concurrent users (unrealistic)
1 MB = ~6,800 concurrent users
The 30-second TTL ensures memory is automatically freed. Even with 100 concurrent conversations, usage stays under 50KB.
Monitoring
Check Redis health and usage:
Connection Test
Active Buffers
Memory Usage
Check TTL
redis-cli -h localhost -p 6379 -a password PING
Troubleshooting
Messages processing too quickly (< 8 seconds)
The processor waits 8 seconds after the last message. If messages are processed before the user finishes:
Increase wait time in IF condition:
if ( Date . now () - Number ( $json . value ) > 10000 ) // 10 seconds instead of 8
Increase processor schedule interval (10s → 15s)
Buffers expiring before processing
If 30-second TTL is too short:
Increase buffer TTL to 60 seconds
Decrease processor schedule to 5 seconds
Check processor isn’t failing/stuck
Connection refused errors
Verify Redis is running: systemctl status redis-server
Check firewall allows port 6379
Test connection: redis-cli -h host -p 6379 -a password PING
Verify password is correct in n8n credentials
Keys not expiring automatically
Confirm expire: true in SET operations
Check TTL is set: redis-cli TTL buffer_51900
Verify Redis config doesn’t disable expiration
Ensure system time is correct
Check for keys without TTL: redis-cli KEYS * | wc -l
Review maxmemory policy: CONFIG GET maxmemory-policy
Monitor with: redis-cli --stat
Manually flush if needed: FLUSHDB (deletes all keys!)
Pipelining
Reduce network round trips by batching commands:
// Instead of 3 separate calls
await redis . set ( 'buffer_123' , 'data' );
await redis . set ( 'ts_123' , timestamp );
await redis . set ( 'meta_123' , metadata );
// Use pipeline (if supported by client)
const pipeline = redis . pipeline ();
pipeline . set ( 'buffer_123' , 'data' , 'EX' , 30 );
pipeline . set ( 'ts_123' , timestamp , 'EX' , 30 );
pipeline . set ( 'meta_123' , metadata , 'EX' , 120 );
await pipeline . exec ();
Key Design
Use consistent key naming for efficient patterns:
// Good: Consistent prefix for pattern matching
buffer_51900769907
ts_51900769907
meta_51900769907
// Bad: Inconsistent naming
user_buffer_51900769907
51900769907 _timestamp
metadata : 51900769907
Security Best Practices
Password protect : Always set requirepass in redis.conf
Bind address : Restrict to bind 127.0.0.1 if local-only
Disable dangerous commands : rename-command FLUSHALL ""
TLS/SSL : Enable for production environments
Firewall : Only allow connections from application servers
Receptor Workflow See buffer implementation
Procesador Workflow Learn how buffers are processed