marekvs
marekvs logo marekvs
Distributed · Redis-compatible · Rust

The key-value store that moves like the tide.

marekvs speaks the Redis protocol, but underneath it's an AP, coordination-free database: no leader, no quorum, no in-memory dataset. Writes are fire-and-forget and converge through hybrid logical clocks and CRDT merges. Any node serves any key.

RESP2 + RESP3 :6379 FROM scratch image Kubernetes operator
redis-cli
$ redis-cli -p 6379
marekvs> SET greeting hello
OK
marekvs> SADD tags rust distributed redis
(integer) 3
marekvs> INCR visits
(integer) 1
# … and every node already has it.
01

Built for movement, not coordination

Redis protocol

RESP2 & RESP3 over the same :6379 your clients already use. Strings, hashes, sets, sorted sets, lists, streams, pub/sub, HyperLogLog.

Convergent replication

Hybrid logical clocks + ORSWOT / PN-counter merges. Concurrent SADDs on different nodes both survive; deletes never resurrect.

Dynamic replication

Any node serves any key. Read a remote key and the node caches it and subscribes to its updates — replication follows demand.

Bounded staleness

Sequence-cursor catch-up plus Merkle anti-entropy repair divergence within seconds. Milliseconds typical, 15 s worst case.

Kubernetes-native

Gossip membership, DNS-seeded discovery, a StatefulSet, and a MarekvsCluster operator with safe scaling and autoscaling.

λ

Lua scripting

EVAL / EVALSHA with Redis-grade atomicity when keys co-locate via hash tags. Script effects replicate, never the script.

02

What we promise — and what we don't

marekvs is AP: available and partition-tolerant, eventually consistent. These are the guarantees the docs stand behind.

GuaranteeWhat it means
Read-your-writesA connection always sees its own prior writes.
Monotonic readsA connection's reads never go backward in time.
ConvergenceGiven no new writes, all replicas reach the same value.
No resurrectionA deleted key stays deleted; tombstones outlive repair.
Exact countersConcurrent INCR/DECR across nodes are never lost.
Bounded stalenessCross-node divergence heals within seconds (15 s worst case).

Not linearizable, not CP, no cross-node transactions, no Redis Cluster MOVED/ASK redirects. Two clients on two nodes can briefly read different values. See Consistency.

03

System shape at a glance

          Redis clients (redis-cli, any RESP driver)
                          │  :6379
        ┌─────────────────┴─────────────────┐
        │        Kubernetes Service          │
        └──┬──────────────┬──────────────┬───┘
           │              │              │
      ┌────┴───┐     ┌────┴───┐     ┌────┴───┐
      │ pod 0  │     │ pod 1  │     │ pod 2  │
      │ RESP   │     │ RESP   │     │ RESP   │
      │ engine │     │ engine │     │ engine │
      │ ondaDB │ ⇄   │ ondaDB │ ⇄   │ ondaDB │   :7373 mesh
      └────────┘     └────────┘     └────────┘
           └──────── chitchat gossip ─────────┘  :7946/udp

Five subsystems per node — RESP frontend, command engine, disk-native storage (ondaDB LSM), replication engine, and the gossip cluster layer. Read the architecture →

04

Honest about performance

~100µs
GET p50 target
500k+
ops/s/node target
8–15 MiB
container image
4096
fixed partitions

marekvs is disk-native and pays a convergent-merge tax, so it trades raw throughput for durability and coordination-free scale. In the KeyDB comparison harness it lands around 0.4–0.6× of an in-RAM store — by design, with the full methodology in Performance.

05

Up in one command

Docker · single node
docker run -d --name marekvs -p 6379:6379 \
  -e MAREKVS_NODE_ID=0 -e MAREKVS_REPLICAS_N=1 \
  ghcr.io/yannick/marekvs:latest

redis-cli -p 6379 ping   # PONG
What you get
  • A Redis-compatible endpoint on :6379
  • Health + Prometheus metrics on :9121
  • Scale to 3 nodes with one env var — see the guide
Full quickstart →

Ready to dive in?

Start with the overview, or jump straight to the API reference.