seedstone

Proves it is correct. Measures that it is fast.

An in-memory key-value store that speaks the Redis protocol. Deterministic by construction, benchmarked with the method beside every number.

  • Rust
  • RESP2
  • Apache-2.0 / MIT
  • single binary
curl -fsSL https://seedstone.io/install.sh | sh

macOS and Linux, x86_64 and arm64. Verifies the release's SHA-256 before installing. Read it first: install.sh.

A seed reproducing a failure seed 0x4f2a9c1e t = 1.800 s c1 SET k v GET k INCR n c2 GET k DEL k SET k v c3 EXPIRE k 60 GET k run 1 ✗ tick 18, assertion failed, trace 0x8b…31 run 2 ✗ tick 18, assertion failed, trace 0x8b…31 ✓ reproduced: same tick, same trace
Illustrative; the real thing is on the testing page.

Fast · KEYS over 7 000 keys, ops/s

5.16× the throughput of Redis on a page cache's walk

  • seedstone3 537
  • Dragonfly2 137
  • Garnet1 517
  • Valkey701
  • Redis686

Same machine, same client, median of three · every cell and the method: benchmarks →

Install

One line. Or any of five others.

The binary is the same on every channel. The packages start a service on loopback; after Homebrew or Cargo, start it with seedstone.

curl

curl -fsSL https://seedstone.io/install.sh | sh

macOS and Linux, x86_64 and arm64. Verifies the release's SHA-256, installs the binary, nothing else.

Docker

docker run -p 6379:6379 seedstone/seedstone --bind 0.0.0.0:6379 --no-auth

Also on GHCR.

Homebrew

brew install seedstonelabs/tap/seedstone

macOS and Linux; as a service with brew services.

Cargo

cargo binstall seedstone

The release archive in seconds; cargo install builds from source.

deb / rpm

A .deb or .rpm with a systemd unit, from the release page; what the service does.

Helm

helm install seedstone oci://ghcr.io/stefanobaldo/charts/seedstone --set auth.noAuth=true

The chart, and what auth.noAuth says.

$ redis-cli127.0.0.1:6379> set greeting hello ex 60OK127.0.0.1:6379> ttl greeting(integer) 60127.0.0.1:6379> get greeting"hello"127.0.0.1:6379> 

Every channel, with checksums, the packaged defaults and the service units: docs/install.md

Correct

The same seed, the same bug. Every time.

The whole server runs inside a deterministic simulation: a virtual clock, a simulated network, scheduled clients. Every completed command folds into a trace hash that depends on two seeds and nothing else.

  1. seed 0x4f2a9c1e
  2. virtual clock
  3. simulated network
  4. scheduled clients
  5. trace 0x8b…31

A concurrency bug, the usual way no seed

  1. run 1✗ tick 6
  2. run 2passed
  3. run 3passed
  4. run 4✗ tick 9, elsewhere

Seen once, gone under the debugger, back in production.

In seedstone seed 0x4f2a9c1e

  1. run 1✗ tick 18 · 0x8b…31
  2. run 2✗ tick 18 · 0x8b…31
  3. run 3✗ tick 18 · 0x8b…31
  4. run 4✗ tick 18 · 0x8b…31

run 4 on another machine, in a fresh process

✓ Reproduced from the seed, byte for byte. Fixed once.

How it is built and how it is tested: docs/testing.md

Fast

Ahead of Redis where a cache lives.

Same machine, same client, median of three runs, throughput in operations per second. Every bar is an engine this server is ahead of; the grey line names the ones level with it.

SET 64 B with EX 60 · depth 64 a cache write with a deadline

Dragonfly reads 4.63 M, level with seedstone: the client's ceiling

2.96× Redis at one I/O thread

  • seedstone4.61 M
  • Garnet4.31 M
  • Redis ×41.82 M
  • Valkey ×41.65 M
  • Redis1.56 M
  • Valkey1.18 M

SET 64 B · depth 64 the plain cache write

Dragonfly 4.65 M and Garnet 4.63 M, level with seedstone: the client's ceiling

2.21× Redis at one I/O thread

  • seedstone4.63 M
  • Valkey ×42.62 M
  • Redis ×42.49 M
  • Redis2.09 M
  • Valkey1.78 M

MGET 16 keys · depth 64 the multi-key read

Garnet reads 629 k, level with seedstone

1.86× Redis at one I/O thread

  • seedstone625 k
  • Dragonfly463 k
  • Valkey ×4442 k
  • Redis ×4398 k
  • Redis336 k
  • Valkey314 k

GET 64 B · depth 64 the pipelined read

Dragonfly reads 4.65 M, level with seedstone: the client's ceiling

1.75× Redis at one I/O thread

  • seedstone4.63 M
  • Garnet4.37 M
  • Valkey ×43.66 M
  • Redis ×43.31 M
  • Redis2.65 M
  • Valkey2.28 M

v0.3.2 on a GCP c4a-standard-16, against Redis 8.10.0, Valkey 9.1.1, Dragonfly df-v1.40.2 and Garnet 2.1.5, 2026-10-11. Every cell at every depth, the CPU per operation, the method fixed before the run, and what the numbers do not say: docs/benchmarks.md

Operated

Says only what it can state truthfully.

Built to be run by someone who is paged for it. A stock Prometheus exporter scrapes it in CI.

INFO, without the fiction

Sections that carry only what the node can state: no resident-set figure it would have to guess, no fork it does not have.

# Memory
maxmemory_policy:allkeys-lru
# Persistence
loading:0
aof_enabled:1
fsync_policy:interval
aof_last_write_status:ok
refusing_executors:0

One JSON line per event

Every line opens with a time, a level and the event's name; a monitor selects by evt and reads fields by name, with no parser of its own.

{"ts":1757800000000,"level":"info","evt":"listening","version":"0.1.1","bind":"0.0.0.0","port":6379}
{"ts":1757800000317,"level":"warn","evt":"error_reply","code":"ERR","cmd":"flushall","msg":"ERR unknown command 'flushall'"}

A password that rotates without a restart

Two passwords are valid while the file holds two, so the server and its clients never have to change in the same moment.

  1. 1add the new line, SIGHUP
  2. 2move the clients, any pace
  3. 3drop the old line, SIGHUP
{"ts":1757800003250,"level":"info","evt":"password_reloaded","passwords":2}

A disk that fails is met with refusal

A write the node cannot keep is not acknowledged: writes are refused until a snapshot is durable, reads are served, and a full disk asks for space, not for a restart.

# the disk is full, --fsync always
> SET order:9 paid
-MISCONF Errors writing to the log: writes are refused until a snapshot is durable
# space freed, a snapshot durable: refusal_ended
> SET order:9 paid
+OK

Flags, output, signals, the password, persistence and INFO: docs/operations.md

Compatibility

A named list. Nothing answered approximately.

RESP2 over TCP, so redis-cli and the ordinary client libraries connect unmodified. Anything outside the list is refused with an error naming the command.

Strings

  • GET
  • SET
  • SETEX
  • SETNX
  • PSETEX
  • MGET
  • INCRBY
  • STRLEN
  • TYPE

Keys & expiry

  • DEL
  • EXISTS
  • EXPIRE
  • PEXPIRE
  • EXPIREAT
  • PEXPIREAT
  • PERSIST
  • TTL
  • PTTL
  • SCAN
  • KEYS
  • DBSIZE
  • FLUSHDB

Server

  • PING
  • ECHO
  • AUTH
  • HELLO
  • INFO
  • CONFIG GET
  • SLOWLOG
  • LATENCY
  • COMMAND
  • CLIENT
  • QUIT

Persistence

  • SAVE
  • BGSAVE
  • LASTSAVE
  • SHUTDOWN

Not here yet — next: hashes, lists, sets, sorted sets, Pub/Sub, RESP3

  • HSET
  • LPUSH
  • SADD
  • ZADD
  • PUBLISH
  • MULTI
  • EVAL
  • SELECT
  • replication
  • clustering
127.0.0.1:6379> set k vOK127.0.0.1:6379> hset h f v(error) ERR unknown command 'hset'127.0.0.1:6379> hello 3(error) NOPROTO unsupported protocol version127.0.0.1:6379> 

Every command, every option, every refusal and every deliberate difference from Redis: docs/compatibility.md

Get started

Try it in the time it takes to read the script.

The installer is the only thing between you and a running server, and it is meant to be read.

curl -fsSL https://seedstone.io/install.sh | sh

Verifies the SHA-256 first · read install.sh · or star it on GitHub