An in-memory cache server built in Zig, evolving toward a drop-in Redis replacement.
kgcache is the cache component of the infrastructure stack being developed at kgxlabs. Its design goals are standalone operation with existing Redis clients and native integration into the future kgx application deployment platform.
Today, kgcache supports a subset of Redis functionality over RESP2, including string storage, expiration, snapshots, and append-only persistence. It is under active development and is not yet a drop-in Redis replacement. See Current status and compatibility for known limitations.
The platform vision and roadmap belong at the kgxlabs organization. This repository documents the cache component, its implementation, and current compatibility.
| Protocol | RESP2 over TCP |
| Address | 127.0.0.1:6379 by default; see Configuration |
| Runtime | Zig 0.16.0+ |
| Data model | Process-local string keys and values |
| Commands | See Commands |
| Persistence | .kgc snapshots and an optional disk-backed AOF journal; see Persistence and AOF |
Build and start the server:
zig build runThen connect from another terminal with redis-cli:
$ redis-cli
127.0.0.1:6379> PING
PONG
127.0.0.1:6379> SET profile:42 "Ada"
OK
127.0.0.1:6379> GET profile:42
"Ada"
127.0.0.1:6379> DBSIZE
(integer) 1The default build installs the executable at zig-out/bin/kgcache. Use a
config file, CLI overrides, or both:
./zig-out/bin/kgcache path/to/kgcache.conf
./zig-out/bin/kgcache path/to/kgcache.conf --port 7000
./zig-out/bin/kgcache --port 7000See Configuration for all settings.
To run kgcache from any directory, add a shell alias to ~/.zshrc (or
~/.bashrc for Bash), adjusting the path to your checkout:
alias kgcache='"/absolute/path/to/kgcache/zig-out/bin/kgcache"'After changing or pulling code, run zig build from the repository root to
update the executable used by the kgcache alias. Restart any running kgcache
server to use the rebuilt executable.
Open a new terminal or reload your shell configuration with source ~/.zshrc
(or source ~/.bashrc), then run:
kgcache /absolute/path/to/kgcache.conf| Doc | Covers |
|---|---|
| Commands | Supported commands, SET options, and compatibility notes |
| Configuration | kgcache.conf file format, every directive, and known gotchas |
| Architecture | Role within kgx, request flow, design trade-offs, repository layout |
| Test organization | Where Zig tests and fixtures belong, test discovery, and checks for test moves |
| Errors and logging | Error propagation, terminal reports, and trace availability |
| Persistence | Short comparison of snapshots and AOF |
| Snapshots | SAVE, BGSAVE, child cleanup, and automatic saving |
| Append-only file | AOF setup, fsync policies, file layout, startup, and rewrite flow |
| Expiration | TTL bookkeeping layout, memory cost, and the planned redesign |
Run the unit test suite:
zig build testThe tests cover command decoding, RESP2 and RESP3 reply encoding, command dispatch, storage, expiration, snapshots, AOF loading and recovery, fsync policies, and AOF rewrites.
See Test organization when adding or moving tests.
Useful commands:
zig fmt src/**/*.zig
zig build
zig build run
zig build test- TCP sessions start in RESP2.
HELLO 2andHELLO 3select the connection's reply mode and report server and connection metadata. BareHELLOreports the current mode. CLIENT INFOreports the caller's connection, and filter-freeCLIENT LISTreports live connections sorted by ID. Both use the documented 22-field subset.CLIENT SETINFOretains library labels for each connection. See CLIENT commands.- Values are strings only; there is no eviction policy, authentication, replication, clustering, pub/sub, or transactions.
- Complete requests are processed in order, including requests split across reads. The input buffer starts at 1 KiB by default and grows as needed up to 1 MiB.
connection-buffer-sizesets the initial capacity, clamped to that cap. - Each encoded request is limited to 1 MiB and 1,024 array elements, including the command name. Limits apply per command, so a pipeline can exceed them overall. Oversized declared sizes or counts receive a protocol error without waiting for the remaining payload, then the connection closes. EOF with a valid unfinished request closes quietly without executing it. See TCP request limits.
- Command errors such as unknown commands or wrong argument counts allow later requests. Malformed RESP input receives a protocol error and ends the session. Reply write or flush failures end the session without appending an error to partial output or executing later commands. Peer resets and broken pipes close quietly. Earlier successful commands remain applied.
- Each reply finishes before the next command starts. A slow reader can pause its worker when socket send space fills. A completed socket write means the local system accepted the bytes; the client may not have read them yet. Shutdown wakes blocked reads and writes before joining workers.
COMMANDsupports registry-based introspection.COMMAND DOCSand module filtering are not supported.- The active-expiration worker currently needs a locking fix before it can safely process TTL keys in a running server. Expired keys are still removed by
GET.
No license file is currently included.