Overview
The RedisAuth class provides persistent authentication storage using Redis. It enables distributed bot deployments by storing encrypted session data in a centralized Redis server, allowing multiple bot instances to share or migrate sessions seamlessly.
Key Features
Distributed Storage : Share sessions across multiple servers
Encrypted Storage : All session data encrypted with AES-256-GCM
High Availability : Leverage Redis replication and clustering
Fast Access : In-memory storage for sub-millisecond latency
Session Migration : Move sessions between servers effortlessly
Automatic Expiry : Optional TTL support for session management
RedisAuth is ideal for production environments with multiple servers, load balancing, or high-availability requirements.
Installation
RedisAuth requires the ioredis package:
Constructor
new RedisAuth(uuid, redis, prefix)
Creates a new RedisAuth instance for managing bot authentication in Redis.
A valid UUID (v4) that uniquely identifies this bot instance. This UUID is used as the encryption key and as part of the Redis key namespace.
An ioredis client instance. This can be a standalone Redis connection, a cluster, or a sentinel configuration.
A string prefix for Redis keys. This helps organize keys and avoid collisions. The final key format is {prefix}:{uuid}:{hash}.
Example
Basic Usage
Redis URL
Redis Cluster
With Authentication
import { Bot , RedisAuth } from "wapi" ;
import { Redis } from "ioredis" ;
import { randomUUID } from "node:crypto" ;
const redis = new Redis ({
host: "localhost" ,
port: 6379 ,
});
const uuid = randomUUID ();
const auth = new RedisAuth ( uuid , redis , "wapi" );
const bot = new Bot ({ auth });
Throws
Error: If the provided UUID is not a valid UUID v4 format
Properties
uuid
The UUID associated with this authentication instance. This is the same UUID provided to the constructor.
const auth = new RedisAuth ( uuid , redis , "wapi" );
console . log ( auth . uuid ); // "550e8400-e29b-41d4-a716-446655440000"
Methods
init()
Initializes the authentication system by loading or creating credentials and setting up the key store.
init (): Promise < IBotAuthInit >
Behavior
Credential Loading : Attempts to load existing credentials from Redis
New Session : If no credentials exist, generates new authentication credentials
Key Store Setup : Initializes the Signal protocol key store for WhatsApp encryption
Cache Population : Populates the in-memory cache with encrypted data
Returns
WhatsApp authentication credentials containing account information, encryption keys, and session state. This is managed internally by the Baileys library.
The Signal protocol key store used for end-to-end encryption. Provides get() and set() methods for managing cryptographic keys.
Example
import { RedisAuth } from "wapi" ;
import { Redis } from "ioredis" ;
import { randomUUID } from "node:crypto" ;
const redis = new Redis ();
const auth = new RedisAuth ( randomUUID (), redis , "wapi" );
// Initialize authentication
const { creds , keys } = await auth . init ();
console . log ( "Credentials loaded:" , !! creds );
console . log ( "Keys initialized:" , !! keys );
This method is called automatically by the Bot class during initialization. You rarely need to call it directly.
save()
Persists the current authentication credentials to Redis.
Behavior
Validation : Ensures credentials have been loaded via init()
Serialization : Converts credentials to JSON format
Encryption : Encrypts the data using AES-256-GCM
Persistence : Writes the encrypted data to Redis
Cache Update : Updates the in-memory cache
Throws
Error: If credentials haven’t been initialized (“Credentials not loaded.”)
Example
import { RedisAuth } from "wapi" ;
import { Redis } from "ioredis" ;
import { randomUUID } from "node:crypto" ;
const redis = new Redis ();
const auth = new RedisAuth ( randomUUID (), redis , "wapi" );
// Initialize and save
await auth . init ();
await auth . save ();
console . log ( "Session saved to Redis" );
The Bot class automatically saves credentials when authentication state changes. Manual calls to save() are typically unnecessary.
remove()
Deletes all authentication data from Redis and clears the cache.
Behavior
Key Discovery : Finds all Redis keys matching the session prefix
Batch Deletion : Deletes all matching keys in a single operation
Cache Clearing : Clears the in-memory cache
Example
Basic Removal
With Bot Instance
import { RedisAuth } from "wapi" ;
import { Redis } from "ioredis" ;
import { randomUUID } from "node:crypto" ;
const redis = new Redis ();
const uuid = randomUUID ();
const auth = new RedisAuth ( uuid , redis , "wapi" );
// Remove session data
await auth . remove ();
console . log ( "Session removed from Redis" );
This operation is irreversible. After calling remove(), the bot will need to re-authenticate (scan QR code or enter OTP) on next startup.
Storage Details
Key Structure
Redis keys follow this pattern:
{prefix}:{uuid}:{md5_hash}
Example:
wapi:550e8400-e29b-41d4-a716-446655440000:5f4dcc3b5aa765d61d8327deb882cf99
Key Naming
Each data key (e.g., “creds”, “pre-key-1”) is MD5-hashed
The hash becomes the final segment of the Redis key
Example: creds → wapi:550e8400-...:5f4dcc3b5aa765d61d8327deb882cf99
Storage
Encryption
Serialization
Values are stored as binary buffers
Retrieved using getBuffer() for efficiency
Encrypted with AES-256-GCM before storage
Cipher : AES-256-GCM (Galois/Counter Mode)
Key : Derived from the bot’s UUID
Security : Authenticated encryption with associated data (AEAD)
Original data is JSON-stringified
Buffers are converted to base64 strings
Result is encrypted with AES-256-GCM
Encrypted bytes are stored in Redis
Complete Examples
Basic Bot
Multi-Bot Setup
Session Migration
With Connection Pool
With Cleanup
import { Bot , RedisAuth } from "wapi" ;
import { Redis } from "ioredis" ;
import { randomUUID } from "node:crypto" ;
const redis = new Redis ({
host: process . env . REDIS_HOST || "localhost" ,
port: parseInt ( process . env . REDIS_PORT || "6379" ),
});
const uuid = randomUUID ();
const auth = new RedisAuth ( uuid , redis , "wapi" );
const bot = new Bot ({ auth });
bot . on ( "qr" , ( qr ) => {
console . log ( "Scan this QR code:" , qr );
});
bot . on ( "open" , ( account ) => {
console . log ( "Connected as:" , account . name );
});
bot . command ( "hello" , ( ctx ) => {
ctx . reply ( "Hello from RedisAuth!" );
});
bot . launch ();
Advanced Configuration
Redis Sentinel
For high availability, use Redis Sentinel:
import { Bot , RedisAuth } from "wapi" ;
import { Redis } from "ioredis" ;
import { randomUUID } from "node:crypto" ;
const redis = new Redis ({
sentinels: [
{ host: "sentinel-1" , port: 26379 },
{ host: "sentinel-2" , port: 26379 },
{ host: "sentinel-3" , port: 26379 },
],
name: "mymaster" ,
});
const auth = new RedisAuth (
randomUUID (),
redis ,
"wapi"
);
const bot = new Bot ({ auth });
bot . launch ();
Redis Cluster
For horizontal scaling:
import { Bot , RedisAuth } from "wapi" ;
import { Cluster } from "ioredis" ;
import { randomUUID } from "node:crypto" ;
const redis = new Cluster ([
{ host: "node1.redis.example.com" , port: 7000 },
{ host: "node2.redis.example.com" , port: 7001 },
{ host: "node3.redis.example.com" , port: 7002 },
], {
redisOptions: {
password: process . env . REDIS_PASSWORD ,
},
});
const auth = new RedisAuth (
randomUUID (),
redis ,
"wapi"
);
const bot = new Bot ({ auth });
bot . launch ();
Advantages
Scalability
Performance
Reliability
Security
✅ Horizontal scaling
✅ Load balancing support
✅ Multiple bot instances
✅ Session sharing
✅ Zero downtime deployments
⚡ In-memory storage
⚡ Sub-millisecond latency
⚡ Efficient caching
⚡ Optimized for reads
⚡ Batch operations
🛡️ High availability
🛡️ Replication support
🛡️ Persistence options
🛡️ Automatic failover
🛡️ Data durability
🔒 AES-256-GCM encryption
🔒 TLS support
🔒 Password authentication
🔒 Network isolation
🔒 No plaintext storage
Best Practices
Follow these recommendations for optimal performance and reliability:
1. Connection Management
// ✅ Good: Reuse Redis connections
const redis = new Redis ();
const auth1 = new RedisAuth ( uuid1 , redis , "wapi" );
const auth2 = new RedisAuth ( uuid2 , redis , "wapi" );
// ❌ Bad: Create new connection per bot
const auth1 = new RedisAuth ( uuid1 , new Redis (), "wapi" );
const auth2 = new RedisAuth ( uuid2 , new Redis (), "wapi" );
2. Error Handling
const redis = new Redis ();
redis . on ( "error" , ( err ) => {
console . error ( "Redis connection error:" , err );
// Implement retry logic or alerting
});
redis . on ( "close" , () => {
console . warn ( "Redis connection closed" );
});
3. Prefix Naming
// ✅ Good: Descriptive, environment-aware prefixes
const prefix = `wapi: ${ process . env . NODE_ENV } :v1` ;
const auth = new RedisAuth ( uuid , redis , prefix );
// ❌ Bad: Generic prefix
const auth = new RedisAuth ( uuid , redis , "bot" );
4. Graceful Shutdown
process . on ( "SIGTERM" , async () => {
await bot . close ();
await redis . quit (); // Graceful disconnect
process . exit ( 0 );
});
Troubleshooting
Connection Issues
Show Cannot connect to Redis
// Check connection with ping
try {
await redis . ping ();
console . log ( "Redis is connected" );
} catch ( error ) {
console . error ( "Redis connection failed:" , error );
}
Show Authentication failures
const redis = new Redis ({
host: "localhost" ,
port: 6379 ,
password: process . env . REDIS_PASSWORD ,
showFriendlyErrorStack: true , // Better error messages
});
Enable connection pooling
Use Redis cluster for distribution
Check network latency between servers
Monitor Redis memory usage
// Implement TTL for sessions (optional)
// Note: This requires custom implementation
await redis . expire ( `wapi: ${ uuid } :*` , 7 * 24 * 60 * 60 ); // 7 days
When to Use
Use RedisAuth
Use LocalAuth
Use MongoAuth
✅ Multi-server deployments
✅ Load-balanced environments
✅ High-availability requirements
✅ Session migration needs
✅ Existing Redis infrastructure
✅ Fast session access required
📁 Single-server deployments
📁 Development/testing
📁 Minimal dependencies
📁 Simple setups
🗄️ Long-term persistence priority
🗄️ Complex queries needed
🗄️ Audit trails required
🗄️ Existing MongoDB infrastructure
See Also