Vault is an in-memory key-value store written in Go.
I built this project to understand how systems like Redis work internally instead of treating them as a black box. The focus was learning storage engines, persistence, crash recovery, caching, concurrency, and networking by implementing them from scratch.
PING
SET <key> <value>
GET <key>
DEL <key>
Example:
SET name adarsh
GET name
DEL name
PING
Vault stores data completely in memory.
Current implementation:
- Thread-safe using
sync.RWMutex - O(1) GET, SET and DELETE
- Hash map + doubly linked list
- LRU (Least Recently Used) eviction
- Configurable maximum capacity
The LRU cache keeps recently accessed keys at the front of the list. Once the configured capacity is reached, the least recently used key is automatically evicted.
The server is built using Go's net package.
Features:
- Multiple client support
- One goroutine per connection
- Simple text-based command protocol
- Graceful shutdown
Example:
nc localhost 5555Every write operation is written to disk before modifying memory.
Each WAL entry contains:
message WALEntry {
uint64 lsn = 1;
string command = 2;
uint32 crc = 3;
}Fields:
| Field | Description |
|---|---|
| LSN | Log Sequence Number |
| Command | Original command |
| CRC | CRC32 checksum for corruption detection |
Protocol Buffers are used to serialize WAL entries.
Instead of storing every log in one file, Vault splits logs into segments.
Example:
data/
└── wal/
├── segment-0
├── segment-1
├── segment-2
Benefits:
- Prevents one huge log file
- Faster startup
- Easier log management
- Automatic log rotation
On startup Vault:
- Opens every WAL segment
- Reads entries in order
- Verifies CRC
- Stops if corruption is detected
- Replays valid commands
- Restores the latest LSN
This allows data to survive crashes and process restarts.
Every WAL entry stores a CRC32 checksum.
During recovery:
Read Entry
│
▼
Verify CRC
│
┌───┴────┐
│ │
Valid Invalid
│ │
▼ ▼
Replay Stop Recovery
If the server crashes while writing an entry, recovery safely stops when it encounters:
io.EOFio.ErrUnexpectedEOF
This prevents replaying partially written data.
Current benchmarks for the in-memory store:
BenchmarkSetKV ~482 ns/op
BenchmarkGetKV ~163 ns/op
BenchmarkDeleteKV ~234 ns/op
Vault
├── cmd/
│ └── vault/
│ └── main.go
│
├── internal/
│ ├── handler/
│ ├── server/
│ ├── store/
│ └── wal/
│
├── proto/
│ └── wal/
│
├── data/
│ └── wal/
│
├── Makefile
├── README.md
├── go.mod
└── go.sum
make buildor
go build -o bin/vault ./cmd/vaultmake runor
./bin/vaultCustom port:
go run ./cmd/vault 8080Implemented:
- Concurrent In-Memory Store
- LRU Cache
- TCP Server
- Multi-client Support
- Write-Ahead Log (WAL)
- WAL Replay
- Crash Recovery
- WAL Segmentation
- WAL Rotation
- CRC32 Validation
- Graceful Shutdown
- Benchmarks
Planned:
- Snapshotting
- WAL Compaction
- TTL Expiration
- RESP Protocol
- Unit Tests
The goal of Vault wasn't to build another Redis clone. I wanted to understand how a storage engine actually works by implementing the core pieces myself.
Through this project I learned about:
- TCP servers in Go
- Concurrent programming
- LRU cache design
- Write-Ahead Logging
- Crash recovery
- Data serialization with Protocol Buffers
- CRC based corruption detection
- Log segmentation and rotation
- Basic storage engine design
The project is still growing as I continue learning more about database internals and distributed systems.