La compresión en bases de datos en memoria como Redis y Valkey puede marcar la diferencia entre un clúster que aguanta picos de tráfico con holgura y uno que se ahoga por latencia, CPU o memoria. Elegir bien el códec —y dónde aplicarlo— no es trivial: no es lo mismo comprimir valores “calientes” en caché que persistencia, ni HTML/JSON que binarios ya comprimidos (imágenes, ZIP, vídeo). Este artículo resume qué códecs son más útiles hoy (LZ4, Zstd, Gzip, Brotli, etc.), dónde aplicarlos en Redis y Valkey, y cuándo cada opción sale a cuenta.
Dónde comprimir en Redis/Valkey (y dónde no)
Antes de ver códecs, es clave entender las capas en las que suele aplicarse compresión:
- Valores (application/client-side)
- Es el patrón más común en producción: comprimir el payload (JSON, HTML, blobs) en el cliente antes de
SET
/HSET
, y descomprimir trasGET
. - Pros: control total (eliges códec y nivel), fácil “feature flag”, ahorra RAM y ancho de banda.
- Contras: CPU en la aplicación, y latencia extra si te pasas de nivel.
- Es el patrón más común en producción: comprimir el payload (JSON, HTML, blobs) en el cliente antes de
- Persistencia (RDB/AOF)
- Redis/Valkey pueden comprimir snapshots (RDB) (históricamente con LZF) y usar AOF (apéndice) que puede comprimirse fuera de banda.
- Pros: menor huella en disco y tiempos de backup más cortos.
- Contras: no afecta a la memoria en caliente; cuidado con costes de CPU al guardar/cargar.
- Tráfico de red
- Lo habitual es no comprimir RESP a nivel de protocolo en producción (TLS ya añade penalización y la compresión a nivel transporte no suele compensar).
- Si hay WAN o inter-DC, considera proxying con compresión selectiva (solo objetos grandes).
Regla práctica: comprime en el cliente si el valor supera un umbral (p. ej., > 1–2 KiB) y es altamente repetitivo (JSON/HTML/CSV/Protobuf), con LZ4 si la latencia es crítica o Zstd si buscas mayor ratio con coste razonable.
Tabla comparativa de códecs habituales
Ratios orientativos en cargas tipo texto (JSON/HTML/logs). Con binarios ya comprimidos (JPEG, MP4, ZIP) el ratio cae y a menudo conviene no comprimir.
Método | Ratio estimado | Ejemplo práctico | Velocidad | Escenario recomendado |
---|---|---|---|---|
Identity | 1× (sin compresión) | Binario 10 MB → 10 MB | Máxima | Datos no comprimibles, latencia ultra-baja |
LZ4 | 1,10× – 1,20× | Texto 10 MB → 8,5–9 MB | Extremadamente alta | Caches con mucha concurrencia (WordPress, APIs) |
Zstd | 1,40× – 1,50× | Texto 10 MB → 6,5–7 MB | Muy alta | Caché profesional, mejor balance “espacio/vel.” |
Gzip | 1,35× – 1,45× | Texto 10 MB → 7–7,5 MB | Alta | Compatibilidad universal |
Brotli | 1,45× – 1,60× | Web assets 10 MB → 6–7 MB | Baja–media | Optimización web/HTTP (no clave en caché RAM) |
Bzip2 | 1,50× – 1,60× | Texto 10 MB → 6,2–6,6 MB | Muy baja | Backups/almacenamiento frío |
LZF | 1,10× – 1,15× | Texto 10 MB → 8,7–9 MB | Extremadamente alta | Legacy/compatibilidad; ganancias modestas |
LZMA | 1,60× – 2,0× | Texto 10 MB → 5–6,5 MB | Muy baja | Archivos offline, espacio por encima de todo |
Zlib | 1,35× – 1,45× | Texto 10 MB → 7–7,5 MB | Alta | Plataformas mixtas, entornos clásicos |
Conclusión rápida:
- LZ4 = “latencia primero”.
- Zstd = “mejor equilibrio moderno”.
- Gzip/Zlib = “compatibilidad universal”.
- Brotli/LZMA/Bzip2 = “ratio máximo, no para tiempo real”.

Redis vs Valkey: ¿qué cambia realmente?
- En entornos profesionales, la compresión de valores se hace en el cliente (middleware/SDK/proxy).
- Redis y Valkey comparten ecosistema y soporte de códecs a través de clientes, middlewares y módulos. Las opciones más frecuentes en caché son
lz4
yzstd
;lzf
se mantiene por compatibilidad o CPU muy limitada;none
para latencia absoluta o datos ya comprimidos. - Valkey suele exponer una variedad amplia de compresores vía integraciones (p. ej., django-valkey), mientras que en Redis verás los mismos códecs en librerías/SDKs maduros. En la práctica, la elección técnica y los resultados de LZ4/Zstd son equivalentes en ambos.
Reglas de decisión (operativas)
- Define un umbral por tamaño
- P. ej., no comprimir valores < 1 KiB; comprimir ≥ 2–4 KiB.
- Aplica “identity” (sin compresión) si el content-type ya viene comprimido (JPEG, MP4, ZIP).
- Elige códec por objetivo
- p99/p999 bajo → LZ4 (nivel default): excelente throughput y latencia.
- Ahorro de RAM/egress sin matar la CPU → Zstd (niveles 1–6; evitar 15+ salvo batch/offline).
- Compatibilidad universal → Gzip/Zlib.
- Almacenamiento frío/backup → Brotli/LZMA/Bzip2 (fuera del plano crítico).
- Evita comprimir dos veces
- Detecta
Content-Encoding
/magics de archivo o usa sniffing (GZIP header, ZIP EOCD, JPEG SOI).
- Detecta
- Observabilidad obligatoria
- Mide ratio, tiempo de (des)compresión, p95/p99 del RTT Redis, uso de CPU.
- Si p99 sube, baja nivel de Zstd o muévete a LZ4.
Ejemplos de integración
Python (Redis/Valkey) con Zstandard y umbral
import redis
import zstandard as zstd
r = redis.Redis(host="localhost", port=6379)
ZSTD_LEVEL = 3
THRESHOLD = 2048 # 2 KiB
cctx = zstd.ZstdCompressor(level=ZSTD_LEVEL)
dctx = zstd.ZstdDecompressor()
def kv_set(key: str, data: bytes):
if len(data) >= THRESHOLD:
compressed = cctx.compress(data)
# Marcamos un prefijo para saber que está comprimido
r.set(key, b"\x28ZSTD\x29" + compressed)
else:
r.set(key, data)
def kv_get(key: str) -> bytes | None:
val = r.get(key)
if not val:
return None
if val.startswith(b"\x28ZSTD\x29"):
return dctx.decompress(val[len(b"\x28ZSTD\x29"):])
return val
Lenguaje del código: PHP (php)
Node.js con LZ4 (latencia crítica)
const Redis = require("ioredis");
const lz4 = require("lz4");
const r = new Redis();
const THRESHOLD = 2048;
const MAGIC = Buffer.from([0x28, 0x4c, 0x5a, 0x34, 0x29]); // (LZ4)
function setLZ4(key, buf) {
if (buf.length < THRESHOLD) return r.setBuffer(key, buf);
const max = lz4.encodeBound(buf.length);
const out = Buffer.allocUnsafe(MAGIC.length + max);
MAGIC.copy(out, 0);
const n = lz4.encodeBlock(buf, out, MAGIC.length);
return r.setBuffer(key, out.subarray(0, MAGIC.length + n));
}
async function getLZ4(key) {
const val = await r.getBuffer(key);
if (!val) return null;
if (val.subarray(0, MAGIC.length).equals(MAGIC)) {
const src = val.subarray(MAGIC.length);
// Sin tamaño original, usar frame o anteponer length si lo necesitas
// Para simplicidad, almacenar LZ4 frame sería preferible aquí.
}
return val;
}
Lenguaje del código: JavaScript (javascript)
En producción es preferible usar frames (LZ4 frame/Zstd frame) que incluyen tamaño original y CRC.
Django-Valkey (config compresor)
VALKEY = {
"BACKENDS": {
"default": {
"HOST": "127.0.0.1",
"PORT": 6379,
"DB": 0,
"COMPRESSION": {
"ALGORITHM": "zstd", # "lz4", "zstd", "gzip", "none"...
"LEVEL": 3, # Ajusta según CPU/latencia
"THRESHOLD": 2048, # En bytes
"HEADER": True # Marca formato/versión
}
}
}
}
Lenguaje del código: PHP (php)
Micro-bench: cómo evaluar en tu entorno
- Genera datasets representativos:
- JSON (1–50 KiB), HTML, logs, blobs binarios (no comprimibles), y mezcla real de tu tráfico.
- Mide por códec y nivel:
- Ratio (bytes_in/bytes_out), t_comp/t_decomp, RTT Redis p50/p95/p99, CPU app/host.
- Prueba con THRESHOLD = {1 KiB, 2 KiB, 4 KiB} y picos de QPS (lecturas 80–95 % típico de caché).
- Repite con LZ4 (default) y Zstd (niveles 1–6).
- Si el p99 sube > 10–15 % frente a “identity”, baja nivel o cambia a LZ4.
- Si RAM es el cuello, sube Zstd a 3–5 y valida CPU.
Casos de uso típicos (qué elegir)
- WordPress/HTML/API cache con QPS alto → LZ4 (o Zstd-1 si p99 lo permite).
- Catálogos JSON/Protobuf con TTL largos → Zstd-3/4 (ahorra RAM y egress).
- Eventos/logs en listas/streams → LZ4 (ingesta masiva, baja latencia).
- Backups/snapshots (RDB/AOF fuera de plano) → Brotli/LZMA/Bzip2.
- Binarios ya comprimidos (imágenes, ZIP) → Identity (no comprimir).
Antipatrones y gotchas
- Over-compression: niveles altos de Zstd/LZMA ↑CPU y ↑p99 sin ganar apenas bytes.
- Overhead en claves pequeñas: para valores < 1 KiB, el header + coste CPU suele perder.
- Compresión doble: detectar formatos comprimidos y saltar.
- Fragmentación: objetos “grandes” (> 512 KiB) pueden presionar el allocator; dividir en chunks si es necesario.
- Composición con pipelines: comprimir en edge (API) pero no en jobs internos con payload ya comprimido.
Recomendaciones finales
- Por defecto moderno: Zstd-3 con THRESHOLD 2–4 KiB y feature flag para volver a LZ4 si el p99 sube.
- Latencia extrema: LZ4 frame, sin niveles exóticos.
- Compatibilidad: Gzip/Zlib si el ecosistema lo requiere.
- Persistencia: comprimir RDB y backups; deja AOF para flujos donde necesites replay con mínimas transformaciones.
Fuentes (lecturas recomendadas)
- Comparativas y análisis recientes de Valkey/Redis y códecs de compresión:
https://www.dragonflydb.io/blog/redis-8-0-vs-valkey-8-1-a-technical-comparison
https://www.dragonflydb.io/guides/valkey-vs-redis
https://www.logicmonitor.com/blog/redis-compression-benchmarking
https://dev.to/konstantinas_mamonas/which-compression-saves-the-most-storage-gzip-snappy-lz4-zstd-1898
https://facebook.github.io/zstd/
https://linuxreviews.org/Comparison_of_Compression_Algorithms
https://quixdb.github.io/squash-benchmark/
https://stephane.lesimple.fr/blog/lzop-vs-compress-vs-gzip-vs-bzip2-vs-lzma-vs-lzma2xz-benchmark-reloaded/
https://cran.r-project.org/web/packages/brotli/vignettes/brotli-2015-09-22.pdf
https://onidel.com/redis-valkey-keydb-vps-2025/
https://django-valkey.readthedocs.io/en/latest/configure/advanced_configurations/
https://experienceleague.adobe.com/en/docs/commerce-operations/implementation-playbook/best-practices/planning/valkey-service-configuration