Vibeleaderboard
Index / tool
Visit github.com
Category
Developer Tools
Rank
No. 3208Tools index

Previous survey · No. 3076 ·

Pricing
Open Source
Type
TOOL
Interfaces
API
GitHub
38 stars
Date

About

Rapto is an in-memory NoSQL key-value database written in Zig with AOF persistence, using a single-threaded event-driven (epoll) server architecture to amortize event-handling costs across concurrent clients. It introduces a 'batch' protocol primitive that lets clients send indivisible ordered sequences of queries, plus features like multi-pattern key scanning, cursors, and CAS-style locking.

What it does

A database server that holds all of its data in RAM and records every incoming request to a log file on disk, so the state can be rebuilt by replaying that log at startup. Clients speak a compact binary protocol in which each request carries a group of commands that run back to back, with nothing from another client slipped in between. Stored values can be integers, decimals, flags, strings, points or lists. Today the only client library is written in Zig, and the server refuses to start on anything other than Linux.

Why it's ranked here

Rapto is a readable study in making a small single-threaded server fast, not a drop-in production store. The author calls it immature, the only client is Zig, and fuzz and integration tests are listed as future work. What sets it apart is the request model: grouping commands so no other client can interleave gives consistent multi-key reads without a transaction system, and each command runs on its own separate code path. It is Apache 2.0 licensed, unit tests run in CI on every push, and the published benchmark figures come from one Intel machine under WSL2 with three-byte keys and values.

What's good

Each key is a single allocation with a two-byte header holding its length and a lock bit, and the value's type rides in the three spare low bits of the pointer, so a key and value pair costs two machine words in release builds, which a compile-time check enforces. One buffer is reused to receive requests, run them and build replies. Pattern scans accept several glob patterns at once and honour a limit and a cursor, so a large scan can be split into slices. The log file carries a magic header and version, and startup can replay it only up to a chosen timestamp.

Tradeoffs

Grouped commands are indivisible but not atomic: if one fails, the rest still run and nothing is rolled back. Keys are capped at 255 bytes and may not contain glob characters. The log is buffered in memory and written and synced to disk only once the configured sync interval has passed, so a crash can lose the latest writes unless that interval is zero. On replay, a group stops at its first non-write command, so writes placed after a read in the same group are skipped. Any connected client can send the shutdown command, and none of the files read show an authentication step.

How to use it well

Treat it as a reference for event-loop and memory-layout technique in Zig, or as a local cache inside a Zig project where you control every client. Put related reads and writes in one group when they need a consistent view, and take a lock when you need a check-then-write that no other client can race, the compare-and-swap pattern the README demonstrates. Set the sync interval to zero if losing recent writes matters. Restart the server between benchmark runs, since memory is not cleared. Clients in other languages and log inspection or compaction tooling are planned, not shipped.

Technical notes+

The executable is built from src/main.zig with full LTO, compiles mimalloc in as static C, and imports rapidhash through translate-c; zprof wraps the allocator and logs unfreed bytes when the server exits. main panics unless the OS is Linux and runs on std.Io.Threaded.init_single_threaded. src/Server.zig loops on Listener.collectEvents, appends each incoming pipeline to the Aof buffer before executing it, and in a deferred block calls Aof.flush (writePositionalAll then file.sync) once aof_sync_seconds have elapsed; zero means every loop iteration. src/state_machine.zig dispatches each Query.Command to a same-named handler via @field, with per-command duplication stated as deliberate, and .down returns error.Shutdown. src/Query.zig classifies commands as read, write or control and pins enum values for protocol compatibility. src/Aof.zig writes a header with a five-byte RAPTO magic, major and minor version and a 128-byte server name; Header.isCompatible requires both to match, batch timestamps come from the .awake clock rather than wall time, and loadPipeline returns at the first query whose kind is not .write, so lock state is never replayed. src/object.zig asserts Key and Value are each usize-sized in ReleaseFast and ReleaseSafe, with Key.Metadata a packed u16 of an 8-bit length and a locked bit. The workflow in .github/workflows/test_unit.yml runs zig build test on ubuntu-latest for every push and pull request.

Observed

License
Apache License 2.0
Language
Zig
Platform support
Linux only; the server entry point panics on any other OS
Interfaces
raptodb executable with server, benchmark, version and help commands; static Zig client library
Install surface
Build from source with zig build; client added as a Zig package via zig fetch from the Git repository
Concurrency model
Single-threaded epoll event loop
Persistence
Append-only file of timestamped request batches, fsynced on a configurable interval
Key limits
1 to 255 bytes, no glob characters
Default address
127.0.0.1:7286
Bundled dependencies
mimalloc, rapidhash and zprof, pinned by commit in build.zig.zon
Testing
Unit tests run in GitHub Actions on push and pull request; README lists fuzz and integration testing as not yet available

Read from README.md, build.zig, build.zig.zon, src/main.zig, src/Server.zig, src/state_machine.zig, src/Aof.zig, src/Query.zig, src/object.zig, .github/workflows/test_unit.yml, LICENSE.

What it can do

  • Store and retrieve key-value data in memory

    Key-value pairs → Stored data

  • Persist data to disk using append-only file logging

    In-memory data changes → AOF persistence file

  • Execute indivisible ordered batches of queries via batch protocol

    Sequence of queries → Batched query results

  • Scan keys using multiple patterns

    Key patterns → Matching keys

  • Iterate large result sets using cursors

    Cursor request → Paginated results

  • Perform CAS-style locking on keys

    Key and expected value → Lock success/failure

Tags

databasekey-value-storenosqlzigin-memoryevent-drivencache

Media

Rapto

Comments (0)

No comments yet

Editorially curated, with community endorsements as a secondary signal. Corrections welcome.