A lightweight, persistent key-value database built from scratch in C++
Redis-inspired Β· event-driven Β· cross-platform Β· containerized
ByteForge is a Redis-inspired key-value store that supports basic CRUD operations over a TCP connection. It is designed around a phonebook use case where string keys map to string values.
This is a personal learning project. The goal is not to build a production database, but to understand how databases, servers, networking, and concurrency actually work under the hood.
The server runs cross-platform on both Windows and Linux using platform-specific networking abstractions.
- Features
- Commands
- Architecture
- Concurrency Model
- Rate Limiting
- Getting Started
- Build Locally
- Run With Docker
- Project Structure
- Roadmap
- License
| Feature | Description |
|---|---|
| π§© Custom HashMap | Hand-rolled hash table with separate chaining for collision resolution and dynamic growth, protected by a std::shared_mutex for concurrent read/write safety |
| β‘ Event-Driven TCP Server | Readiness-based event loop supporting many concurrent connections without one thread per client β epoll on Linux, IOCP on Windows (adapted via zero-byte WSARecv), both behind a shared IEventLoop interface selected automatically at compile time |
| π§΅ Thread Pool | Fixed pool of 3 worker threads executing actual command work (GET/INSERT/DELETE), decoupled from connection count |
| π Command Parser | Parses INSERT, GET, and DELETE commands from raw TCP bytes |
| π Snapshot Scheduler | Background thread that automatically triggers RDB snapshots on a fixed interval |
| πΎ Hybrid Persistence | AOF logs every write in real time; RDB snapshots dump the full database every 5 minutes; AOF resets after each snapshot |
| π¦ Rate Limiting | Per-IP and global request throttling using the Token Bucket algorithm |
| π Graceful Shutdown | Type stop to cleanly flush data and join all threads |
| π³ Docker Support | Multi-stage containerized build targeting Linux |
| π Authentication | In progress |
Connect to the server using ncat or any TCP client:
ncat 127.0.0.1 6625| Command | Description | Example |
|---|---|---|
INSERT key value |
Inserts or updates a key-value pair | INSERT Ahmed 51020651 |
GET key |
Retrieves the value for a key | GET Ahmed |
DELETE key |
Removes a key-value pair | DELETE Ahmed |
Client (ncat / custom client)
β
β TCP
βΌ
Cross-Platform TCP Server
(Winsock2 / Linux sockets)
β
βΌ
Event Loop (readiness-based)
epoll (Linux) / IOCP (Windows)
behind a shared IEventLoop interface
β watches all client sockets;
β reports which ones are ready
βΌ
ββββΆ Rate Limiter (Token Bucket)
β per-IP + global request cap
β β
β βΌ
β Command Parser
β β
β βΌ
β Thread Pool (3 workers)
β executes actual GET/INSERT/DELETE
β β
β βΌ
β HashMap (in-memory store)
β shared_mutex: readers run concurrently,
β writers get exclusive access
β
ββββΆ Persistence Layer
βββ appendonly.log (real-time AOF log)
βββ snapshot.log (periodic RDB snapshot)
β²
SnapshotScheduler
(background thread, every 5 min)
| Component | Protection | Strategy |
|---|---|---|
| Event Loop | Single dedicated thread | Watches all sockets for readiness; never blocks on I/O |
| Client jobs | ThreadPool + std::condition_variable |
Only dispatched once a socket is actually readable |
| Connections | busySockets guard (std::mutex) |
Prevents duplicate recv() jobs for the same socket |
| HashMap | std::shared_mutex |
Multiple readers, exclusive writers |
| AOF stream | std::mutex |
Single writer at a time |
| Snapshot | SnapshotScheduler thread |
Sleeps on interval, wakes on shutdown |
| Rate limiter | std::mutex per map + global |
Per-IP and global window isolated |
ByteForge uses the Token Bucket algorithm for rate limiting β the same approach used by Stripe, GitHub, and AWS.
- Each IP gets a bucket of tokens (default: 10)
- Each request consumes one token
- Tokens refill at a fixed rate (default: 5/sec)
- A global cap limits total requests per second across all IPs (default: 1000)
- Blocked requests are dropped immediately without consuming a worker thread
- C++17 compiler
- CMake 3.15+
- Docker (optional)
- nmap/ncat for testing
For local builds:
- Windows: MSVC / MinGW with Winsock2
- Linux: GCC / Clang with POSIX sockets
cmake -S . -B build
cmake --build buildRun:
./build/Debug/KV_Database.exe # Windows
./build/KV_Database # LinuxThe server starts on port 6625 by default. Type stop to shut it down cleanly.
Build the image:
docker build -t byteforce:latest .Run the container:
docker run -d -p 6625:6625 --name my-byteforce-db byteforce-db:latestConnect using:
ncat 127.0.0.1 6625kv-db/
βββ src/
β βββ main.cpp
β βββ Server/
β β βββ Server.h
β β βββ Server.cpp
β βββ Networking/
β β βββ NetworkTypes.h
β β βββ EventLoop.h
β β βββ EpollEventLoop.h / .cpp
β β βββ IocpEventLoop.h / .cpp
β β βββ EventLoopFactory.h
β βββ UserSession/
β β βββ UserSession.h / .cpp
β β βββ Connection.h
β βββ RAM/
β β βββ HashMap.h
β β βββ HashMap.cpp
β βββ Storage/
β β βββ Persistence.h
β β βββ Persistence.cpp
β βββ Worker/
β β βββ ThreadPool.h
β β βββ ThreadPool.cpp
β β βββ SnapshotScheduler.h
β β βββ SnapshotScheduler.cpp
β βββ Limit/
β β βββ Limiter.h
β β βββ Limiter.cpp
β βββ Tests/
β βββ test_hashmap.cpp
β βββ test_threadpool.cpp
βββ Dockerfile
βββ .dockerignore
βββ CMakeLists.txt
βββ README.md
- Custom HashMap with separate chaining
- TCP server with Winsock2
- Cross-platform networking support (Windows/Linux)
- Command parser (INSERT, GET, DELETE)
- AOF persistence with real-time logging
- RDB snapshots every 5 minutes
- AOF reset after each snapshot
- Thread pool for concurrent client sessions
- HashMap thread safety with shared_mutex
- Persistence thread safety with mutex
- Snapshot scheduler background thread
- Clean server shutdown
- Data recovery on restart (RDB + AOF replay)
- Unit tests with GoogleTest (HashMap + ThreadPool)
- Docker containerization (multi-stage Linux build)
- Rate limiting with Token Bucket algorithm
- Cross-platform event-driven architecture (epoll / IOCP)
- Route idle-session socket cleanup through Server's connection teardown path
- TCP fragmentation / message framing (LineBuffer)
- Authentication (username + password)
This project is licensed under the MIT License. See LICENSE for details.
Built from scratch as a self-learning project to understand C++, networking, persistence, and systems programming.