Skip to content

Benchmarks

django-vcache vs django-valkey vs Django RedisCache

All benchmarks: Python 3.14, granian ASGI server (uvloop), 1 worker, 2ms simulated network RTT. Each request performs 6 async cache operations (get, get_many, set, set compressed, incr, get compressed).

django-valkey configured with AsyncValkeyCache + msgpack serializer + zstd compressor + libvalkey C parser — its best-case async configuration.

Throughput (uncapped, 300 concurrency, 30s)

django-vcache django-valkey Django RedisCache
Requests/sec 1,643 1,125 284
Avg latency 182 ms 266 ms 1,047 ms
P99 latency 197 ms 292 ms 1,188 ms
Peak RSS 213 MB 177 MB 600 MB
Valkey connections 2 301 4,480

Memory efficiency (rate-limited to 1,000 req/s, 250 concurrency, 120s)

To compare memory fairly, all backends are rate-limited to the same throughput:

django-vcache django-valkey Django RedisCache
Actual req/s 999 999 300 (can't keep up)
Peak RSS 109 MB 135 MB 1,739 MB
Valkey connections 3 252 9,926

At equal throughput, django-vcache uses the least memory because it doesn't need hundreds of TCP connections with per-connection buffers. Django RedisCache can't even hit the target rate and still balloons to 1.7 GB.

vs django-valkey (1.5x faster, fewer connections)

django-valkey's AsyncValkeyCache is genuinely async (no sync_to_async wrapper), making it far better than Django's built-in RedisCache. However, it still opens one TCP connection per concurrent request (301 at 300 concurrency, 252 at 250). django-vcache multiplexes all operations over 2 connections.

vs Django RedisCache (5.8x faster)

Django's RedisCache wraps every async call in sync_to_async, spawning a thread per operation. Under load this creates thousands of TCP connections and unbounded memory growth.

Why django-vcache is different

django-vcache uses a Rust I/O driver with a single multiplexed connection. No connection pool to tune, no per-connection overhead. The throughput advantage grows with network latency — multiplexing pipelines operations across one connection instead of waiting for round-trips on hundreds or thousands.

Reproduce

docker compose build
docker compose up -d valkey

# Throughput test (uncapped)
docker compose run --rm --cap-add NET_ADMIN app \
  python bench_compare.py --duration 30 -c 300 --delay 1 -w 1

# Memory efficiency test (rate-limited)
docker compose run --rm --cap-add NET_ADMIN app \
  python bench_compare.py --duration 120 -c 250 --delay 1 -w 1 --rate-limit 1000