filedb: A Disk-Based Key-Value Store Inspired by Bitcask in Zig

filedb: A Disk-Based Key-Value Store Inspired by Bitcask in Zig

Summary

filedb is a Zig-implemented, disk-based key-value store drawing inspiration from the Bitcask paper by Riak. It offers high throughput and efficient O(1) record fetching by storing metadata in a log-structured hashtable and data in append-only files. The project also provides a Redis-compatible client for easy integration and benchmarking.

Repository Info

Updated on December 17, 2025
View on GitHub

Tags

Click on any tag to explore related repositories

Introduction

filedb is a key-value store implemented in Zig, inspired by the design principles of Bitcask by Riak. It's engineered to provide a high-performance, disk-based solution for storing and retrieving data. The system manages record metadata in a log-structured hashtable while storing actual data in append-only disk files, ensuring efficient operations and data integrity through mechanisms like file rotation, compaction, and periodic syncing.

Installation

As filedb is a Zig library, integration typically involves adding it as a dependency to your Zig project. For those looking to interact with it as a service, filedb also offers a Redis-compatible client. Detailed build and installation instructions for the library or the Redis client can be found directly within the project's GitHub repository.

Examples

filedb provides a clear API for common key-value operations:

const filedb = @import("filedb");
const std = @import("std");

pub fn main() !void {
    var gpa = std.heap.GeneralPurposeAllocator(.{}){};
    const allocator = gpa.allocator();
    defer _ = gpa.deinit();

    var db = try filedb.init(allocator, null);
    defer db.deinit();

    // Insert a key-value pair
    try db.put("hello", "world");

    // Retrieve a value
    const value = try db.get("hello");
    std.debug.print("Retrieved: {s}\n", .{value}); // Output: Retrieved: world

    // Delete a key-value pair
    try db.delete("hello");

    // Attempt to retrieve after deletion
    const deleted_value = db.get("hello");
    if (deleted_value) |v| {
        std.debug.print("Still found: {s}\n", .{v});
    } else {
        std.debug.print("Key not found after deletion.\n", .{}); // Output: Key not found after deletion.
    }

    // List all keys (example, requires allocation)
    var keys = try db.list(allocator);
    defer allocator.free(keys);
    std.debug.print("Keys in DB: {any}\n", .{keys});
}

For users interacting with the Redis-compatible client, the experience is familiar:

127.0.0.1:6379> PING
PONG
127.0.0.1:6379> get abcd
(nil)
127.0.0.1:6379> set abcd def
OK
127.0.0.1:6379> get abcd
"def"

Why Use filedb?

filedb offers several compelling advantages for developers seeking an efficient key-value store:

  • O(1) Record Fetching: Thanks to its metadata structure, retrieving records is an O(1) operation, ensuring fast access times.
  • Constant-Sized Metadata: The in-memory metadata store maintains a constant size regardless of the value's size, optimizing memory usage.
  • High Throughput: By utilizing an append-only file for insertions, filedb achieves high write throughput.
  • Redis Compatibility: The availability of a Redis-compatible client allows for easy integration into existing systems and familiar interaction patterns.

Links