valkey-lab

curl -fsSL https://cachecannon.cc/install.sh | bash

A deep-dive benchmarking tool for Valkey. Go beyond quick throughput checks. Mix workloads, control rate, watch tail latency per second, and find your server's saturation point.

Install, run, analyze

Quick start

Zero-config defaults, just run it

Realistic workload

16 connections, pipeline 32, Zipfian keys

Warm cache, GETs only

Prefill every key, then benchmark reads

Fixed-rate latency

Pin load to 500K req/s, measure latency

Saturation search

Find max rate where p999 stays under SLO

Export + view

Save time-series to Parquet, open dashboard

~/bench

Short flags are compatible with valkey-benchmark (-c, -P, -d, etc.), but examples here use --named-arguments so you can read them. Full reference in VALKEY-LAB.md.

Designed to read, not to parse

Benchmark output is something you stare at. valkey-lab uses a deliberate color hierarchy so the numbers you care about stand out and the rest stays quiet. req/s and p999 are bold white. Everything else is dimmed. Errors turn red the instant they appear. The header reprints every 25 rows so you never lose context during a long run.

This is not cosmetic. When you're watching a 5-minute saturation search or debugging a latency spike in production, the difference between scanning a wall of monochrome numbers and seeing the one column that matters bolded is the difference between catching the problem and scrolling past it.

Bold what matters

req/s and p999 are bold white. Time, p50, p90, p99, p9999, max, hit% are all dimmed. Your eye goes straight to throughput and the latency percentile that usually trips SLOs.

Color-coded signals

Cyan for config labels. Green for PASS. Red for FAIL and errors. Yellow for throughput warnings. Dim for separators and low-signal columns. Every color has a reason.

Per-second streaming

One row per second with full p50 through p9999 and max. Spikes that disappear in aggregate percentiles show up as individual rows in the time series.

valkey-lab --connections 16 --pipeline 32 --ratio 80:20
time UTC req/s p50 p90 p99 p999 p9999 max err/s hit% ──────── ───── ─────── ─────── ─────── ─────── ─────── ─────── ───── ──── 14:30:11 524K 48 µs 89 µs 156 µs 312 µs 891 µs 1.24 ms 0 79% 14:30:12 531K 47 µs 87 µs 152 µs 298 µs 756 µs 1.12 ms 0 79% 14:30:13 528K 47 µs 88 µs 154 µs 305 µs 812 µs 1.18 ms 0 79% ───────────────────────────────────────────────────────────────────────────────────── RESULTS (60s) ───────────────────────────────────────────────────────────────────────────────────── throughput 531K req/s, 0% errors bandwidth 684 Mbps RX, 312 Mbps TX hit rate 79.3% (25.2M hit, 6.6M miss) latency p50 p90 p99 p999 p9999 max GET 47 µs 87 µs 154 µs 301 µs 756 µs 1.12 ms SET 52 µs 94 µs 167 µs 334 µs 891 µs 1.45 ms connections 16 active, 0 failed

Go deeper than a quick benchmark

valkey-benchmark is good for quick throughput checks. valkey-lab builds on that foundation with controls for the questions that come next: what happens under mixed traffic, at a controlled rate, with realistic key distributions, over time?

Mixed GET/SET

Concurrent GETs and SETs at any ratio

Rate limiting

Measure latency at a fixed request rate

Prefill & warmup

Warm cache and discard early samples

Per-second tail latency

Catch spikes that hide in aggregates

Key distribution

Zipfian hot-key patterns

Exportable results

Parquet time-series + web dashboard

valkey-lab --connections 16 --pipeline 32 --ratio 80:20

Find max SLO-compliant throughput

Ramps request rate geometrically until your latency SLO breaks. Classifies failures as throughput-limited (server can't keep up) or latency-exceeded (server keeps up but tail latency blows).

valkey-lab saturate --slo-p999 1ms --connections 16 --pipeline 32
valkey-lab saturate --slo-p999 1ms
━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━ STEP 1 — PASS SLO: 500K @ p999 ≤ 1ms Result: 498K @ p999=312 µs Headroom: 69% ━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━ ━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━ STEP 2 — PASS SLO: 525K @ p999 ≤ 1ms Result: 523K @ p999=445 µs Headroom: 55% ━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━ ━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━ STEP 3 — FAIL — Throughput Limited SLO: 551K @ p999 ≤ 1ms Result: 412K @ p999=845 µs Throughput: 75% (need 90%) ━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━ ━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━ STEP 4 — FAIL — Latency Exceeded SLO: 579K @ p999 ≤ 1ms Result: 401K @ p999=3.40 ms Latency: p999 3400us > 1000us SLO ━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━ ──────────────────────────────────────────────────────── MAX COMPLIANT THROUGHPUT: 525K req/s