A Redis-compatible server built from scratch in Node.js β implementing the RESP protocol, dual-layer persistence (AOF + RDB), master/replica replication, Pub/Sub messaging, and transactions. Comes with an interactive React sandbox to explore commands and visualise internal storage in real time.
Try it β https://abhinov007.github.io/Redis_Clone/
Type Redis commands and watch the internal database, expiry store, AOF log, RDB snapshot, and Pub/Sub channels update live.
- RESP Protocol β full Redis Serialization Protocol parser with incremental TCP chunk handling
- 4 data types β Strings, Lists, Hashes, Sets
- Key-space completeness β multi-key duplicate-aware
EXISTS, key type inspection (TYPE), atomic key renaming with TTL preservation (RENAME), and Redis-compliant glob pattern matches (*,?,[a-z]) via converted regular expressions (KEYS). - String & List completeness β conditional writes (
SETNX), multiple key mutations/fetches (MSET/MGET), value appending (APPEND), key length fetching (STRLEN), delta mutators (INCRBY/DECRBY), and bounds-safe negative-indexed list operations (LINDEX,LSET,LTRIMwith auto-deletion on empty). - Key expiry β
SET key value EX seconds, lazy eviction on read + active probabilistic sweep every 100 ms - 60+ commands across all data types
- AOF β every write appended to
database.aof; replayed on startup via the live command handler (no duplicate parser) - RDB β debounced async JSON snapshot to
dump.rdb; blocks only on graceful shutdown - Priority rule β AOF takes precedence over RDB on startup (matches Redis behaviour, prevents double-apply of mutations)
MULTI/EXEC/DISCARDβ commands queued and executed atomically; per-command error isolation insideEXEC
SUBSCRIBE/UNSUBSCRIBE/PUBLISH- Channel β subscriber socket mapping with automatic cleanup on disconnect
- Master generates a replication ID and maintains a 1 MB circular backlog
- Full resync (RDB snapshot) and partial resync (
+CONTINUEfrom backlog offset) - Replica 6-state handshake with auto-reconnect and
REPLCONF ACKheartbeats - Write commands propagated to all replicas in RESP format
- Replica enforces read-only mode for client connections
- Error boundary β any unhandled exception inside a command returns
-ERRto the client; server keeps running - Graceful shutdown β
SIGINT/SIGTERMflush a final synchronous RDB snapshot before exit - Active expiry sweep β probabilistic Fisher-Yates sample, re-sweeps immediately when >25 % of sample expired
| Command | Example |
|---|---|
SET key value [EX seconds] |
SET name Alice EX 60 |
GET key |
GET name |
MSET key value [key value β¦] |
MSET k1 v1 k2 v2 |
MGET key [key β¦] |
MGET k1 k2 k3 |
SETNX key value |
SETNX lock 1 |
STRLEN key |
STRLEN name |
APPEND key value |
APPEND log " entry" |
INCR key |
INCR hits |
DECR key |
DECR stock |
INCRBY key n |
INCRBY score 10 |
DECRBY key n |
DECRBY score 5 |
| Command | Example |
|---|---|
LPUSH key val [val β¦] |
LPUSH queue a b c |
RPUSH key val [val β¦] |
RPUSH queue a b c |
LPOP key |
LPOP queue |
RPOP key |
RPOP queue |
LLEN key |
LLEN queue |
LRANGE key start stop |
LRANGE queue 0 -1 |
LINDEX key index |
LINDEX queue 0 |
LSET key index value |
LSET queue 0 newval |
LTRIM key start stop |
LTRIM queue 0 99 |
| Command | Example |
|---|---|
HSET key field value [field value β¦] |
HSET user:1 name Bob age 30 |
HGET key field |
HGET user:1 name |
HDEL key field [field β¦] |
HDEL user:1 age |
HGETALL key |
HGETALL user:1 |
HLEN key |
HLEN user:1 |
HEXISTS key field |
HEXISTS user:1 name |
| Command | Example |
|---|---|
SADD key member [member β¦] |
SADD tags redis nosql |
SREM key member [member β¦] |
SREM tags nosql |
SMEMBERS key |
SMEMBERS tags |
SCARD key |
SCARD tags |
SISMEMBER key member |
SISMEMBER tags redis |
SUNION key [key β¦] |
SUNION s1 s2 |
SINTER key [key β¦] |
SINTER s1 s2 |
SDIFF key [key β¦] |
SDIFF s1 s2 |
| Command | Example |
|---|---|
EXISTS key [key β¦] |
EXISTS name age |
TYPE key |
TYPE mylist |
RENAME key newkey |
RENAME tmp result |
KEYS pattern |
KEYS user:* |
DEL key |
DEL name |
FLUSHALL |
FLUSHALL |
| Command | Description |
|---|---|
MULTI |
Begin transaction block |
EXEC |
Execute all queued commands atomically |
DISCARD |
Cancel the transaction |
| Command | Example |
|---|---|
SUBSCRIBE channel [channel β¦] |
SUBSCRIBE news alerts |
UNSUBSCRIBE [channel β¦] |
UNSUBSCRIBE news |
PUBLISH channel message |
PUBLISH news "Hello World" |
| Command | Description |
|---|---|
PING |
Returns PONG |
END |
Close the current connection |
redis_clone/
βββ server.js # TCP server entry point
βββ startup.js # Persistence loading + replica init
βββ RESPParser.js # Incremental RESP protocol parser
βββ client.js # Interactive CLI client
β
βββ commands/
β βββ command.js # All 60+ command handlers
β
βββ middleware/
β βββ transactions.js # MULTI/EXEC/DISCARD + command queue
β βββ replication.js # Read-only guard, REPLCONF/PSYNC routing
β
βββ storage/
β βββ database.js # In-memory Map store (string/list/hash/set)
β βββ expiry.js # TTL store, lazy + active sweep eviction
β
βββ persistence/
β βββ aof.js # Append-Only File (dependency-injected replay)
β βββ rdb.js # Debounced async JSON snapshot
β
βββ protocol/
β βββ resp.js # RESP encoding helpers
β
βββ messaging/
β βββ pubsub.js # Pub/Sub channel β socket mapping
β
βββ replication/
β βββ master.js # Replication ID, backlog, propagation
β βββ replica.js # 6-state handshake + streaming state machine
β
βββ tests/
β βββ phase1Test.js # Stability: async RDB, error boundary, shutdown (11 tests)
β βββ phase2Test.js # Correctness: expiry sweep, AOF replay, INCR/DECR (14 tests)
β βββ phase3Test.js # Completeness: key-space, strings, lists, sets (55 tests)
β βββ loadTest.js # Throughput / latency benchmark with histogram
β βββ TestParser.js # RESP parser smoke test
β βββ clientTest.js # SET/GET integration test
β βββ replicationTest.js # Replication suite (18 tests)
β
βββ workflow.html # Interactive Mermaid architecture diagrams
β
βββ sandbox/ # React + Vite interactive browser sandbox
βββ src/
β βββ engine/ # Browser simulation of server internals
β β βββ database.js
β β βββ expiry.js
β β βββ commands.js
β β βββ aof.js
β β βββ rdb.js
β β βββ pubsub.js
β βββ components/
β β βββ Terminal.jsx # REPL with command history
β β βββ StorageInspector.jsx # 5-tab storage visualiser
β β βββ KeyCard.jsx # Per-key card with live TTL countdown
β β βββ ResponseLine.jsx # Colour-coded RESP response renderer
β βββ hooks/
β β βββ useRedisEngine.js # Central state hook (useRef engine, useState snapshots)
β βββ App.jsx
βββ vite.config.js
βββ package.json
- Node.js v18+
node server.jsServer starts on port 6379 by default.
# Custom port
node server.js --port 6380
# Start as a replica of another instance
node server.js --port 6380 --replicaof localhost 6379# Built-in CLI client
node client.js
# netcat (inline commands)
echo -e "*1\r\n\$4\r\nPING\r\n" | nc localhost 6379Terminal 1 β Master
node server.jsTerminal 2 β Replica
node server.js --port 6380 --replicaof localhost 6379Writes on the master propagate automatically. The replica does a full RDB sync on first connect and a partial resync on reconnect using the replication backlog.
Terminal 1 β Subscriber
node client.js # then type: SUBSCRIBE newsTerminal 2 β Publisher
node client.js # then type: PUBLISH news "Hello World"Each suite is self-contained β it spawns its own server instance(s) on isolated ports and cleans up after itself.
# Stability (async RDB, error boundary, graceful shutdown)
node tests/phase1Test.js
# Correctness (active expiry, AOF replay across all types, INCR/DECR)
node tests/phase2Test.js
# Completeness (60+ commands: key-space, strings, lists, sets)
node tests/phase3Test.js
# Performance benchmark (throughput, p50/p95/p99 latency, histogram)
node tests/loadTest.js [clients] [requestsPerClient] [set|get|mix|pipeline]Run all suites in sequence:
node tests/phase1Test.js && node tests/phase2Test.js && node tests/phase3Test.js| Mode | Description |
|---|---|
mix (default) |
Alternating SET and GET |
set |
SET only |
get |
GET only (seed with set first) |
pipeline |
16 commands per batch |
node tests/loadTest.js 100 500 mixThe sandbox/ directory is a React + Vite app that simulates the server entirely in the browser. No server or Node.js needed.
cd sandbox
npm install
npm run devOpen http://localhost:5173 to explore:
| Tab | What it shows |
|---|---|
| Database | Live key cards with type badges (string / list / hash / set), flashes on write |
| Expiry | Live TTL countdown bars for keys with EX |
| AOF Log | Append-only log updating after every write |
| RDB Snapshot | Full JSON snapshot regenerated after every write |
| Pub/Sub | Active channels and subscriber counts |
Open workflow.html in a browser for interactive Mermaid diagrams covering:
- Full system overview
- Request lifecycle (GET/SET β parser β middleware β command handler β AOF/RDB β replication)
- Replication handshake and replica state machine
- Pub/Sub message flow
- Persistence write and recovery paths (AOF priority rule)
- MULTI/EXEC transaction flow
- Module dependency map
MIT