This is a submission for the Redis AI Challenge: Beyond the Cache.
I built a complete multiplayer Plants vs Zombies tower defense game that showcases Redis as a multi-model platform - demonstrating capabilities far beyond simple caching. This isn't just a game with Redis caching; it's a game where Redis IS the entire backend infrastructure.
- Multiplayer tower defense with real-time gameplay
- Plant-based defense against waves of zombies
- Real-time leaderboards with 5 different categories
- Smart username suggestions with plant-themed names
- Live statistics and comprehensive player tracking
- Persistent game state across sessions and reconnections
- Frontend: Vanilla JavaScript with Socket.IO for real-time communication
- Backend: Node.js with Express and Socket.IO
- Database: Redis as the primary and only database (no SQL database)
- Real-time: Redis Pub/Sub for live multiplayer updates
- Analytics: Redis data structures for statistics and metrics
- Deployment: Docker-ready with production configuration
git clone <repository-url>
cd plants-vs-zombies-redis
./start.sh- Game:
http://localhost:3001- Full multiplayer gameplay - API:
http://localhost:3001/api- RESTful API endpoints - Health:
http://localhost:3001/api/health- System monitoring - Leaderboards:
http://localhost:3001/api/leaderboard/high_scores- Live rankings - Statistics:
http://localhost:3001/api/stats- Real-time game metrics
- Join games with suggested usernames like
GardenMaster,ZombieSlayer - Place plants and watch zombies spawn in real-time
- See other players' actions instantly via Socket.IO + Redis Pub/Sub
- ๐ High Scores - Overall game performance rankings
- ๐ง Zombies Killed - Combat effectiveness leaderboard
- ๐ฑ Plants Planted - Strategic deployment rankings
- ๐ Waves Completed - Survival achievement board
- ๐ฎ Games Won - Victory statistics leaderboard
{
"totalGames": 156,
"totalPlayers": 42,
"activeGames": 8,
"zombiesKilled": 2847,
"plantsPlanted": 1923
}This project demonstrates Redis as a complete multi-model platform using 7 different Redis data structures to replace traditional database architectures entirely:
Redis completely replaces SQL databases
// Store complete game states as JSON
await redis.hset(`game:${gameId}:state`, 'data', JSON.stringify({
players: {...},
plants: [...],
zombies: [...],
currentWave: 5,
gameStatus: 'playing'
}));
// Player profiles with statistics and achievements
await redis.hset(`player:${playerId}:data`, {
score: 15420,
zombiesKilled: 89,
plantsPlanted: 156,
gamesWon: 12,
achievements: JSON.stringify(['first_win', 'zombie_slayer'])
});Beyond the Cache: No SQL database exists - Redis stores all persistent data including complex nested game states, player profiles, and session information.
Live multiplayer without polling
// Broadcast plant placements to all players instantly
await redis.publish(`game:${gameId}:updates`, JSON.stringify({
type: 'plant_placed',
plant: {type: 'sunflower', row: 2, col: 3},
playerId: 'GardenMaster',
timestamp: Date.now()
}));
// Wave completion notifications
await redis.publish(`game:${gameId}:events`, JSON.stringify({
type: 'wave_completed',
wave: 5,
nextWaveIn: 30000,
message: 'Wave 5 completed! Prepare for boss wave!'
}));Beyond the Cache: Eliminates polling entirely - all real-time updates use Redis Pub/Sub for sub-millisecond message delivery to unlimited concurrent players.
Complete game replay and analytics pipeline
// Record every game action for complete audit trail
await redis.xadd(`game:${gameId}:events`, '*', {
action: 'plant_placed',
playerId: 'ZombieSlayer',
plantType: 'peashooter',
position: JSON.stringify({row: 1, col: 4}),
cost: 100,
timestamp: Date.now()
});
// Analytics pipeline processes all events
const gameEvents = await redis.xrange(`game:${gameId}:events`, '-', '+');
// Can reconstruct any game state from event historyBeyond the Cache: Provides complete event sourcing capabilities - every game action is recorded for replay, analytics, and debugging without external event streaming systems.
Real-time competitive rankings
// Update multiple leaderboards simultaneously during gameplay
await redis.zadd('leaderboard:high_scores', player.score, playerId);
await redis.zadd('leaderboard:zombies_killed', player.zombiesKilled, playerId);
await redis.zadd('leaderboard:plants_planted', player.plantsPlanted, playerId);
// Get top 10 players with scores instantly
const topPlayers = await redis.zrevrange('leaderboard:high_scores', 0, 9, 'WITHSCORES');
// Returns: [['EpicSunflower', '25840'], ['GardenMaster', '23150'], ...]Beyond the Cache: Automatic ranking system with O(log N) performance - no manual sorting or separate ranking calculations needed.
FIFO zombie queues for game mechanics
// Each game lane has its own zombie queue
await redis.lpush(`game:${gameId}:lane:0:zombies`, JSON.stringify({
type: 'basic_zombie',
health: 100,
speed: 1.0,
spawnTime: Date.now()
}));
// Process zombies in spawn order (FIFO)
const nextZombie = await redis.rpop(`game:${gameId}:lane:0:zombies`);Beyond the Cache: Perfect queue management for game mechanics - zombies spawn and move in correct order with atomic operations.
Active games and player tracking
// Track all active games
await redis.sadd('active_games', gameId);
// Track players in each game
await redis.sadd(`game:${gameId}:players`, playerId);
// Efficient membership checks
const isPlayerInGame = await redis.sismember(`game:${gameId}:players`, playerId);
const activeGameCount = await redis.scard('active_games');Beyond the Cache: Efficient session management with set operations - instant membership checks and lobby management without complex queries.
Memory-efficient statistics
// HyperLogLog for unique player counting (uses only ~12KB for millions of players)
await redis.pfadd('hll:unique_players', playerId);
const uniquePlayerCount = await redis.pfcount('hll:unique_players');
// Global game statistics
await redis.incr('counter:total_games');
await redis.incrby('counter:zombies_killed', zombiesKilledThisGame);
await redis.incrby('counter:plants_planted', plantsPlantedThisGame);
// Rate limiting with expiring counters
await redis.incr(`rate_limit:${playerId}:${currentHour}`);
await redis.expire(`rate_limit:${playerId}:${currentHour}`, 3600);Beyond the Cache: Built-in analytics platform - memory-efficient unique counting, global statistics, and rate limiting without external analytics systems.
// What most applications do - Redis as cache layer
const cachedUser = await redis.get(`cache:user:${userId}`);
if (!cachedUser) {
const user = await database.query('SELECT * FROM users WHERE id = ?', userId);
await redis.setex(`cache:user:${userId}`, 3600, JSON.stringify(user));
return user;
}
return JSON.parse(cachedUser);// What this project demonstrates - Redis as the entire backend
class GameEngine {
constructor(redis) {
this.redis = redis; // Redis IS the database, not a cache
}
async placePlant(gameId, playerId, plantType, row, col) {
// 1. Primary Database: Update game state
const gameState = await this.redis.hget(`game:${gameId}:state`, 'data');
// ... modify game state ...
await this.redis.hset(`game:${gameId}:state`, 'data', JSON.stringify(gameState));
// 2. Real-time: Notify all players instantly
await this.redis.publish(`game:${gameId}:updates`, JSON.stringify({
type: 'plant_placed', plant: newPlant, playerId
}));
// 3. Event Sourcing: Record for replay/analytics
await this.redis.xadd(`game:${gameId}:events`, '*', {
action: 'plant_placed', playerId, plantType, row, col
});
// 4. Leaderboards: Update rankings
await this.redis.zadd('leaderboard:plants_planted', ++player.plantsPlanted, playerId);
// 5. Analytics: Update global statistics
await this.redis.incr('counter:plants_planted');
await this.redis.pfadd('hll:unique_players', playerId);
// 6 different Redis capabilities in one operation!
}
}- Zero SQL databases - Redis handles all data persistence
- No cache invalidation - No cache layer because Redis IS the primary database
- Event-driven design - Pub/Sub eliminates all polling
- Complete audit trails - Streams provide event sourcing out of the box
- Sub-millisecond operations - All data operations in memory
- Zero cache misses - No cache layer means no cache invalidation complexity
- Horizontal scalability - Architecture ready for Redis Cluster deployment
- Memory efficiency - HyperLogLog and optimized data structures
- Real-time multiplayer - Up to 4 players per game with instant synchronization
- Persistent progression - Player statistics and achievements survive server restarts
- Live competitive rankings - 5 different leaderboard categories updating in real-time
- Smart user experience - Auto-generated usernames, responsive design, health monitoring
- Docker support - Single container and multi-container configurations
- Production logging - Structured logging with multiple log levels
- Health monitoring - Comprehensive health checks and metrics endpoints
- Complete documentation - Deployment guides, API documentation, development workflows
Player Action โ Socket.IO โ Game Engine โ Redis Multi-Model Operations:
โโโ HSET (Primary DB)
โโโ PUBLISH (Real-time)
โโโ XADD (Event Sourcing)
โโโ ZADD (Leaderboards)
โโโ SADD (Session Mgmt)
โโโ INCR (Analytics)
โโโ PFADD (Unique Counting)
โ
All Players โ Socket.IO โ Pub/Sub Notifications โ Redis
Single game action triggers 7 different Redis data structures simultaneously!
This Plants vs Zombies game proves that Redis is not just a cache - it's a complete, powerful, multi-model platform that can:
โ
Replace entire database stacks - No PostgreSQL, MongoDB, or MySQL needed
โ
Provide real-time capabilities - Built-in Pub/Sub eliminates message queues
โ
Handle complex analytics - HyperLogLog, counters, and sorted sets for insights
โ
Scale to millions of users - Ready for Redis Cluster horizontal scaling
โ
Deliver consistent sub-millisecond performance - All operations in memory
The game is fully functional, production-ready, and demonstrates Redis as the complete backend infrastructure for modern real-time applications.
Redis isn't just "beyond the cache" - it's beyond the need for anything else! ๐ป๐งโโ๏ธ
Ready to experience Redis multi-model power? Start defending your lawn at http://localhost:3001! ๐ฎโจ