Skip to content
ParticleDB

Key-value: ParticleDB and Redis

ParticleDB serves Redis clients over the Redis protocol (RESP) and its own native key-value protocol. This page compares it with Redis in two durability modes, each against the Redis setting that gives the same guarantee.

Mode ParticleDB Redis Reply sent Writes lost on power failure
Asynchronous --kv-durability async (default) appendfsync everysec Before fsync ParticleDB: writes since the last fsync, about 1.7 ms in our tests (fsync runs continuously). Redis: up to 1 second.
Durable --durability sync appendfsync always After fsync None: every acknowledged write is on disk.

ParticleDB operations per second divided by Redis operations per second, one command per request, over RESP. Above 1.00x means ParticleDB is faster.

Operation Async, 8 clients Async, 64 clients Async, 512 clients Durable, 8 clients Durable, 64 clients Durable, 512 clients
SET 1.27x 2.21x 4.81x 1.78x 1.27x 1.58x
GET 1.60x 3.13x 7.11x 1.56x 3.08x 7.04x
INCR 1.46x 3.12x 6.88x 1.70x 1.08x 1.88x
LPUSH 1.49x 3.19x 6.45x 1.74x 1.12x 1.99x
HSET 1.51x 3.05x 5.06x 1.75x 1.16x 1.91x

ParticleDB scales with the server’s cores: throughput keeps rising as clients are added. With a single client the result is decided by per-request latency rather than cores; see the full tables.

ParticleDB --kv-durability async against Redis appendfsync everysec.

SET, one command per request
10k100k1.00M1864512concurrent clientsoperations per second (log)redis-everysec 1 clients: 76,118 ops/sredis-everysec 8 clients: 184,215 ops/sredis-everysec 64 clients: 201,032 ops/sredis-everysec 512 clients: 186,393 ops/spdb-async 1 clients: 68,266 ops/spdb-async 8 clients: 233,152 ops/spdb-async 64 clients: 443,773 ops/spdb-async 512 clients: 897,390 ops/spdb-async-native 1 clients: 68,327 ops/spdb-async-native 8 clients: 302,244 ops/spdb-async-native 64 clients: 521,024 ops/spdb-async-native 512 clients: 553,506 ops/s
GET, one command per request
10k100k1.00M10.00M1864512concurrent clientsoperations per second (log)redis-everysec 1 clients: 86,504 ops/sredis-everysec 8 clients: 231,070 ops/sredis-everysec 64 clients: 245,796 ops/sredis-everysec 512 clients: 228,156 ops/spdb-async 1 clients: 86,650 ops/spdb-async 8 clients: 368,629 ops/spdb-async 64 clients: 769,476 ops/spdb-async 512 clients: 1,623,240 ops/spdb-async-native 1 clients: 93,092 ops/spdb-async-native 8 clients: 708,725 ops/spdb-async-native 64 clients: 3,415,933 ops/spdb-async-native 512 clients: 3,214,184 ops/s
INCR, one command per request
10k100k1.00M10.00M1864512concurrent clientsoperations per second (log)redis-everysec 1 clients: 85,211 ops/sredis-everysec 8 clients: 232,492 ops/sredis-everysec 64 clients: 252,751 ops/sredis-everysec 512 clients: 234,974 ops/spdb-async 1 clients: 75,109 ops/spdb-async 8 clients: 339,363 ops/spdb-async 64 clients: 788,769 ops/spdb-async 512 clients: 1,617,664 ops/spdb-async-native 1 clients: 76,536 ops/spdb-async-native 8 clients: 492,904 ops/spdb-async-native 64 clients: 1,034,431 ops/spdb-async-native 512 clients: 967,861 ops/s
LPUSH, one command per request
10k100k1.00M10.00M1864512concurrent clientsoperations per second (log)redis-everysec 1 clients: 82,799 ops/sredis-everysec 8 clients: 211,634 ops/sredis-everysec 64 clients: 224,012 ops/sredis-everysec 512 clients: 207,346 ops/spdb-async 1 clients: 71,288 ops/spdb-async 8 clients: 315,153 ops/spdb-async 64 clients: 714,908 ops/spdb-async 512 clients: 1,337,532 ops/s

- - - Redis 7.2.7 (appendfsync everysec)   ━━ ParticleDB over RESP (–kv-durability async)   ━━ ParticleDB native KV protocol (–kv-durability async)

The native key-value protocol, asynchronous mode, against Redis:

Operation 8 clients 64 clients 512 clients
SET 1.64x 2.59x 2.97x
GET 3.07x 13.90x 14.09x
INCR 2.12x 4.09x 4.12x
All asynchronous results
Operation Clients Pipeline Redis ops/s ParticleDB RESP ops/s ParticleDB native ops/s p99 ms (Redis / RESP / native)
SET 1 1 76,118 68,266 (0.90x) 68,327 (0.90x) 0.02 / 0.02 / 0.02
SET 8 1 184,215 233,152 (1.27x) 302,244 (1.64x) 0.08 / 0.05 / 0.03
SET 64 1 201,032 443,773 (2.21x) 521,024 (2.59x) 0.70 / 1.34 / 0.31
SET 512 1 186,393 897,390 (4.81x) 553,506 (2.97x) 5.30 / 49.43 / 58.37
SET 1 16 367,935 256,508 (0.70x) 221,875 (0.60x) 0.08 / 0.06 / 0.06
SET 8 16 704,422 1,011,502 (1.44x) 884,271 (1.26x) 0.43 / 0.20 / 0.17
SET 64 16 722,018 1,467,997 (2.03x) 550,216 (0.76x) 4.87 / 69.33 / 76.98
SET 512 16 640,440 1,470,331 (2.30x) 549,610 (0.86x) 34.05 / 182.32 / 191.79
GET 1 1 86,504 86,650 (1.00x) 93,092 (1.08x) 0.01 / 0.01 / 0.01
GET 8 1 231,070 368,629 (1.60x) 708,725 (3.07x) 0.09 / 0.08 / 0.01
GET 64 1 245,796 769,476 (3.13x) 3,415,933 (13.90x) 0.51 / 1.13 / 0.03
GET 512 1 228,156 1,623,240 (7.11x) 3,214,184 (14.09x) 2.39 / 0.89 / 0.32
GET 1 16 470,946 442,819 (0.94x) 469,980 (1.00x) 0.07 / 0.07 / 0.03
GET 8 16 1,188,489 1,576,930 (1.33x) 3,439,170 (2.89x) 0.20 / 0.18 / 0.03
GET 64 16 1,208,791 3,768,671 (3.12x) 9,201,634 (7.61x) 1.68 / 1.39 / 0.23
GET 512 16 1,086,199 4,474,941 (4.12x) 9,105,514 (8.38x) 15.17 / 8.09 / 1.93
INCR 1 1 85,211 75,109 (0.88x) 76,536 (0.90x) 0.01 / 0.01 / 0.01
INCR 8 1 232,492 339,363 (1.46x) 492,904 (2.12x) 0.04 / 0.04 / 0.02
INCR 64 1 252,751 788,769 (3.12x) 1,034,431 (4.09x) 0.49 / 1.20 / 0.26
INCR 512 1 234,974 1,617,664 (6.88x) 967,861 (4.12x) 2.29 / 0.79 / 2.92
INCR 1 16 537,361 436,964 (0.81x) 346,485 (0.64x) 0.03 / 0.04 / 0.04
INCR 8 16 1,166,854 2,158,263 (1.85x) 1,690,443 (1.45x) 0.15 / 0.13 / 0.08
INCR 64 16 1,196,083 4,511,391 (3.77x) 999,519 (0.84x) 1.56 / 0.93 / 1.79
INCR 512 16 1,140,930 4,523,900 (3.97x) 1,020,847 (0.89x) 13.37 / 5.14 / 14.75
LPUSH 1 1 82,799 71,288 (0.86x) - 0.01 / 0.02
LPUSH 8 1 211,634 315,153 (1.49x) - 0.05 / 0.04
LPUSH 64 1 224,012 714,908 (3.19x) - 0.55 / 1.29
LPUSH 512 1 207,346 1,337,532 (6.45x) - 3.49 / 0.77
LPUSH 1 16 404,925 309,297 (0.76x) - 0.06 / 0.05
LPUSH 8 16 674,187 1,164,057 (1.73x) - 0.48 / 0.16
LPUSH 64 16 670,544 1,451,012 (2.16x) - 4.14 / 1.68
LPUSH 512 16 653,771 1,464,682 (2.24x) - 31.33 / 54.53
HSET 1 1 79,416 70,142 (0.88x) - 0.01 / 0.02
HSET 8 1 199,626 301,992 (1.51x) - 0.06 / 0.04
HSET 64 1 209,798 639,061 (3.05x) - 0.59 / 1.28
HSET 512 1 195,810 990,884 (5.06x) - 3.80 / 0.92
HSET 1 16 335,565 257,979 (0.77x) - 0.08 / 0.06
HSET 8 16 522,275 806,361 (1.54x) - 0.57 / 0.28
HSET 64 16 523,017 873,462 (1.67x) - 5.34 / 4.00
HSET 512 16 512,038 922,858 (1.80x) - 38.54 / 47.45
redis-benchmark mix 1 1 81,392 70,718 (0.87x) - 0.01 / 0.01
redis-benchmark mix 8 1 176,792 173,568 (0.98x) - 0.04 / 0.04
redis-benchmark mix 64 1 174,774 173,086 (0.99x) - 0.21 / 0.22
redis-benchmark mix 512 1 164,499 160,419 (0.98x) - 1.67 / 1.93
redis-benchmark mix 1 16 672,856 429,642 (0.64x) - 0.03 / 0.04
redis-benchmark mix 64 16 1,144,916 870,862 (0.76x) - 1.07 / 3.06
redis-benchmark mix 512 16 1,136,084 873,683 (0.77x) - 11.72 / 23.86

Data: run of 2026-10-31 with the ParticleDB 1.1.19-rc.17 release candidate (commit 14813b4d9).

ParticleDB --durability sync against Redis appendfsync always. Each write waits for an fsync of about 1.7 ms on this volume, which sets the single-client rate for both systems. Every ParticleDB configuration is also killed with kill -9 and every acknowledged write is verified after restart.

The native key-value protocol, durable mode, against Redis:

Operation 8 clients 64 clients 512 clients
SET 2.23x 1.53x 1.73x
GET 3.03x 13.58x 14.55x
INCR 2.07x 1.49x 2.28x
All durable results
Operation Clients Pipeline Redis ops/s ParticleDB RESP ops/s ParticleDB native ops/s p99 ms (Redis / RESP / native)
SET 1 1 572 1,041 (1.82x) 1,051 (1.84x) 2.23 / 1.83 / 1.80
SET 8 1 2,441 4,342 (1.78x) 5,431 (2.23x) 3.87 / 2.79 / 2.75
SET 64 1 27,215 34,605 (1.27x) 41,727 (1.53x) 4.68 / 4.12 / 4.02
SET 512 1 98,831 155,820 (1.58x) 171,468 (1.73x) 10.57 / 32.88 / 33.11
SET 1 16 8,704 16,007 (1.84x) 15,919 (1.83x) 2.08 / 2.30 / 1.92
SET 8 16 30,768 63,222 (2.05x) 66,252 (2.15x) 5.80 / 4.84 / 4.38
SET 64 16 224,498 272,784 (1.22x) 214,271 (0.95x) 10.90 / 60.90 / 54.18
SET 512 16 465,591 1,063,772 (2.28x) 518,057 (1.11x) 41.09 / 305.76 / 250.51
GET 1 1 87,048 86,873 (1.00x) 91,153 (1.05x) 0.01 / 0.01 / 0.01
GET 8 1 234,559 365,324 (1.56x) 709,947 (3.03x) 0.09 / 0.08 / 0.01
GET 64 1 247,115 762,339 (3.08x) 3,354,919 (13.58x) 0.50 / 1.16 / 0.03
GET 512 1 230,320 1,622,391 (7.04x) 3,351,659 (14.55x) 2.39 / 0.89 / 0.31
GET 1 16 471,989 441,914 (0.94x) 462,057 (0.98x) 0.07 / 0.07 / 0.03
GET 8 16 1,189,800 1,597,774 (1.34x) 3,396,994 (2.86x) 0.21 / 0.18 / 0.03
GET 64 16 1,207,474 5,453,360 (4.52x) 9,871,788 (8.18x) 1.66 / 1.52 / 0.21
GET 512 16 1,091,555 6,877,056 (6.30x) 9,808,988 (8.99x) 15.56 / 8.09 / 1.74
INCR 1 1 573 1,045 (1.82x) 1,053 (1.84x) 1.92 / 1.79 / 1.83
INCR 8 1 2,554 4,340 (1.70x) 5,288 (2.07x) 3.72 / 2.74 / 2.70
INCR 64 1 31,037 33,646 (1.08x) 46,127 (1.49x) 4.01 / 2.80 / 2.83
INCR 512 1 126,064 236,917 (1.88x) 286,797 (2.28x) 4.29 / 3.65 / 4.08
INCR 1 16 9,060 16,154 (1.78x) 15,978 (1.76x) 1.91 / 1.83 / 1.83
INCR 8 16 35,488 68,490 (1.93x) 71,610 (2.02x) 3.83 / 2.77 / 2.87
INCR 64 16 342,567 465,894 (1.36x) 377,026 (1.10x) 5.57 / 3.19 / 4.69
INCR 512 16 820,416 2,163,346 (2.64x) 962,392 (1.17x) 16.91 / 8.09 / 14.22
LPUSH 1 1 573 1,044 (1.82x) - 1.89 / 1.79
LPUSH 8 1 2,498 4,335 (1.74x) - 3.69 / 2.70
LPUSH 64 1 30,469 34,002 (1.12x) - 4.08 / 2.80
LPUSH 512 1 113,668 225,717 (1.99x) - 5.80 / 4.18
LPUSH 1 16 9,010 15,892 (1.76x) - 1.94 / 1.83
LPUSH 8 16 34,868 69,244 (1.99x) - 3.95 / 2.80
LPUSH 64 16 269,552 413,172 (1.53x) - 7.05 / 4.88
LPUSH 512 16 543,981 1,047,227 (1.93x) - 32.90 / 65.27
HSET 1 1 573 1,044 (1.82x) - 1.89 / 1.81
HSET 8 1 2,479 4,334 (1.75x) - 3.69 / 2.74
HSET 64 1 30,272 35,065 (1.16x) - 4.11 / 2.80
HSET 512 1 109,608 208,905 (1.91x) - 6.26 / 5.14
HSET 1 16 8,992 15,864 (1.76x) - 1.91 / 1.83
HSET 8 16 34,640 70,698 (2.04x) - 3.95 / 2.80
HSET 64 16 239,502 413,766 (1.73x) - 8.09 / 5.28
HSET 512 16 439,584 949,804 (2.16x) - 41.68 / 38.01
redis-benchmark mix 1 1 573 1,044 (1.82x) - 1.96 / 1.80
redis-benchmark mix 8 1 2,473 4,337 (1.75x) - 3.68 / 2.70
redis-benchmark mix 64 1 19,472 34,317 (1.76x) - 3.98 / 2.75
redis-benchmark mix 512 1 96,598 149,422 (1.55x) - 6.65 / 4.19
redis-benchmark mix 1 16 9,074 16,132 (1.78x) - 1.98 / 1.81
redis-benchmark mix 8 16 35,234 - -
redis-benchmark mix 64 16 227,207 373,834 (1.65x) - 5.33 / 5.00
redis-benchmark mix 512 16 665,599 779,971 (1.17x) - 17.61 / 25.49

Data: run of 2026-10-31 with the ParticleDB 1.1.19-rc.17 release candidate (commit 14813b4d9).

Machine AWS c8g.metal-48xl, 192 Graviton4 vCPUs, 500 GB EBS data volume (4 KiB fsync median 1.73 ms)
CPU placement Server pinned to 48 cores (0-47), load generator to 48 other cores (48-95)
Redis 7.2.7, default io-threads (single-threaded command execution)
Load generators memtier_benchmark 2.1.4, redis-benchmark 7.2.7, and the suite’s own RESP and native drivers; the same driver runs against both servers in each cell
Data 100,000 keys, 32-byte values; list and hash operations spread across keys
Clients and pipelining 1, 8, 64 and 512 connections; 1 and 16 commands per request
Statistic Median over alternating rounds in one session; p99 latency per cell

Run each server alone on the machine, pinned to the same cores, and drive it from other cores.

redis.conf used for both modes (change the last line to appendfsync always for durable mode):

bind 127.0.0.1
protected-mode no
tcp-backlog 4096
maxclients 20000
timeout 0
tcp-keepalive 0
save ""
aof-use-rdb-preamble yes
appendonly yes
appendfsync everysec
Terminal window
taskset -c 0-47 redis-server ./redis.conf --port 6379 --dir /data/redis

Asynchronous mode:

Terminal window
taskset -c 0-47 particledb start --no-auth \
--durability groupsync --kv-durability async \
--data-dir /data/pdb --redis-addr 127.0.0.1:6379

Durable mode: replace the second line with --durability sync --kv-durability sync.

Each cell runs a 2-second warm-up and an 8-second timed run with the client pinned to the other cores. For example, SET with 64 clients and no pipelining:

Terminal window
taskset -c 48-95 memtier_benchmark -s 127.0.0.1 -p 6379 --protocol=redis \
-t 8 -c 8 --ratio=1:0 --key-pattern=R:R --key-minimum=1 --key-maximum=100000 \
-d 32 --pipeline=1 --test-time=8 --hide-histogram

For GET use --ratio=0:1 after loading the keys; for pipelining use --pipeline=16; for other client counts change -t (threads) and -c (connections per thread) so that t x c is 1, 8, 64 or 512. The classic mix uses the stock tool:

Terminal window
taskset -c 48-95 redis-benchmark -h 127.0.0.1 -p 6379 -c 64 -P 1 -d 32 -r 100000 -n 1000000 \
-t set,get,incr,lpush,hset --csv

The results on this page were produced by our benchmark suite, which runs the same cells with a verifying load driver: it checks every reply and the final state of the keys, alternates Redis and ParticleDB rounds in one session, and kills each ParticleDB configuration with kill -9 to confirm that acknowledged writes survive. The native-protocol rows use the same driver over the ParticleDB native key-value protocol.

Use the median of the timed rounds per cell, with p99 latency, and publish the server versions, configuration and machine details listed under Test setup.

See Benchmarks and methodology for the reporting rules.