{"schemaVersion":1,"id":"https://lucioduran.com/es/blog/valkey-redis-fork-performance-analysis","url":"https://lucioduran.com/es/blog/valkey-redis-fork-performance-analysis","title":"Valkey vs Redis: Migrando 14TB de Datos en Producción, Lo Que la Documentación No Cubre","description":"Análisis del I/O multi-threaded de Valkey, el protocolo RESP3 y las optimizaciones de memoria. Incluye una migración real desde Redis 7.2, metodología de benchmarks y los problemas complejos encontrados en producción.","language":"es","datePublished":"2026-02-02","dateModified":null,"contentFormat":"text/markdown","content":"Databases\n\n# Valkey vs Redis: Migrando 14TB de Datos en Producción, Lo Que la Documentación No Cubre\n\n2026-02-0210 min lectura\n\nLucio Durán\nEngineering Manager & AI Solutions Architect\n\nTambién disponible en: [English](<https://lucioduran.com/blog/valkey-redis-fork-performance-analysis>)\n\n## Por Qué Existe Valkey (La Versión Corta)\n\nRedis Labs cambió su licencia de BSD a una licencia dual SSPL/RSAL en marzo 2024. Esto hizo imposible que los proveedores cloud ofrezcan Redis manejado sin un acuerdo comercial. [AWS](<https://aws.com/>), Google, Oracle y otros respaldaron el fork [Valkey](<https://valkey.io/>) bajo la Linux Foundation con licencia BSD-3-Clause.\n\nMás allá de la política, la pregunta relevante es si el software es mejor. Las siguientes secciones examinan la ingeniería real.\n\n## RESP3: El Protocolo que Nadie Usa (Pero Debería)\n\nRESP3 (Redis Serialization Protocol v3) se introdujo en Redis 6 pero casi nadie lo usa porque RESP2 sigue funcionando y la mayoría de las librerías de cliente lo usan por defecto. Esto es un error.\n\nRESP3 introduce respuestas tipadas. En RESP2, todo es o un string, integer, array o error. Tu librería cliente tiene que adivinar tipos:\n\n```\n# Respuesta RESP2 a HGETALL\n*4\n$4\nname\n$5\nLucio\n$3\nage\n$2\n38\n\n# El cliente tiene que saber que elementos alternos\n# forman pares key-value y que \"38\" probablemente\n# debería ser un integer\n```\n\n```\n# Respuesta RESP3 a HGETALL\n%2\n$4\nname\n$5\nLucio\n$3\nage\n:38\n\n# El prefijo % significa \"mapa con 2 entradas\"\n# El prefijo : significa \"esto es un integer\"\n# No hay que adivinar nada\n```\n\nEl impacto práctico es más grande de lo que parece. En servicios Node.js usando ioredis, pasar a RESP3 elimina un montón de llamadas a ` parseInt() ` y ` JSON.parse() ` del lado de la aplicación. El uso de CPU en los servers de app puede bajar ~8% en el hot path, no porque el protocolo sea más rápido por la red, sino porque dejamos de hacer coerción de tipos redundante.\n\nPara habilitar RESP3 en una conexión existente:\n\n```python\n# Python con valkey-py (fork de redis-py)\nimport valkey\n\nclient = valkey.Valkey(\n host='valkey-primary.internal',\n port=6379,\n protocol=3 # Esto manda HELLO 3 al conectar\n)\n\n# Ahora las respuestas son nativamente tipadas\nresult = client.hgetall('user:1001')\n# Devuelve: {'name': 'Lucio', 'age': 38}\n# age ya es un int, no b'38'\n```\n\n## I/O Multi-Threaded: Donde Valkey Realmente Diverge\n\nRedis tiene ` io-threads ` desde la versión 6, pero estaba limitado a operaciones de escritura y se sentía como algo puesto a último momento. Valkey llevó esto más lejos con threading tanto de lectura como escritura, y la implementación es genuinamente distinta.\n\nLa arquitectura:\n\n```\n Thread Principal\n ┌──────────┐\n │ Ejecución│\n │ de │\n │ Comandos │\n │ (single) │\n └────┬─────┘\n │\n ┌──────────┼──────────┐\n │ │ │\n ┌────┴───┐ ┌───┴────┐ ┌──┴─────┐\n │ I/O │ │ I/O │ │ I/O │\n │Thread 1│ │Thread 2│ │Thread 3│\n │ read/ │ │ read/ │ │ read/ │\n │ write │ │ write │ │ write │\n └────────┘ └────────┘ └────────┘\n```\n\nLa ejecución de comandos sigue siendo single-threaded (esto es fundamental para el modelo de consistencia de Valkey/Redis, no se necesitan locks). Pero el parsing de I/O y la serialización de respuestas pasan en paralelo entre threads. Aquí va una configuración que funciona bien en instancias de 8 cores:\n\n```conf\n# valkey.conf\nio-threads 4\nio-threads-do-reads yes\n\n# No configurar io-threads más alto que tu core count menos 2\n# El thread principal + tareas de background necesitan CPU\n# 4 threads en 8 cores es típicamente el punto óptimo\n\n# Aumentar el backlog para workloads con muchas conexiones\ntcp-backlog 4096\n```\n\nEsto se benchmarkeó sistemáticamente usando ` valkey-benchmark ` con distintas cantidades de conexiones:\n\n```bash\n# Conexión única (no se espera beneficio del threading)\nvalkey-benchmark -h 127.0.0.1 -p 6379 -c 1 -n 1000000 \\\n -t set,get -d 256 --threads 1\n\n# 200 conexiones (donde el threading importa)\nvalkey-benchmark -h 127.0.0.1 -p 6379 -c 200 -n 5000000 \\\n -t set,get -d 256 --threads 4\n\n# 1000 conexiones (stress test)\nvalkey-benchmark -h 127.0.0.1 -p 6379 -c 1000 -n 10000000 \\\n -t set,get -d 256 --threads 8\n```\n\nResultados en un r7g.2xlarge (8 vCPU, 64GB):\n\n| Conexiones | Redis 7.2 (ops/s) | Valkey 8.0 1-thread (ops/s) | Valkey 8.0 4-thread (ops/s) |\n| --- | --- | --- | --- |\n| 1 | 142,000 | 144,000 | 143,000 |\n| 50 | 398,000 | 405,000 | 612,000 |\n| 200 | 445,000 | 451,000 | 891,000 |\n| 500 | 462,000 | 468,000 | 1,024,000 |\n| 1000 | 471,000 | 475,000 | 1,143,000 |\n\nCon 1 conexión, sin diferencia. Con 1000 conexiones, Valkey con 4 threads de I/O entrega 2.4x el throughput. No es magia, es simplemente que la lectura/escritura de sockets y la serialización de respuestas están paralelizadas mientras la ejecución de comandos sigue serializada.\n\n## La Migración: 14TB en 12 Shards\n\nEl setup: 12 clusters Redis (cada uno con un primary + 2 réplicas) manejando datos de sesión, feature flags, rate limiting y un pipeline de analytics en tiempo real. Dataset total: ~14TB entre todos los shards.\n\nLa estrategia de migración fue reemplazo rolling sin downtime:\n\n```bash\n#!/bin/bash\n# Versión simplificada de nuestro script de migración\n# La versión real tenía manejo de errores, rollback y hooks de monitoreo\n\nSHARD=$1\nREDIS_HOST=\"redis-${SHARD}.internal\"\nVALKEY_HOST=\"valkey-${SHARD}.internal\"\n\n# Paso 1: Configurar Valkey como réplica de Redis\nvalkey-cli -h $VALKEY_HOST \\\n REPLICAOF $REDIS_HOST 6379\n\n# Paso 2: Esperar a que termine el sync\nwhile true; do\n STATUS=$(valkey-cli -h $VALKEY_HOST INFO replication \\\n | grep master_sync_in_progress)\n if [[ $STATUS == *\"0\"* ]]; then\n echo \"Sync completo para shard $SHARD\"\n break\n fi\n sleep 5\ndone\n\n# Paso 3: Verificar integridad de datos\nREDIS_KEYS=$(redis-cli -h $REDIS_HOST DBSIZE | awk '{print $2}')\nVALKEY_KEYS=$(valkey-cli -h $VALKEY_HOST DBSIZE | awk '{print $2}')\nDIFF=$((VALKEY_KEYS - REDIS_KEYS))\n\nif [ ${DIFF#-} -gt 100 ]; then\n echo \"ERROR: Diferencia de keys: Redis=$REDIS_KEYS Valkey=$VALKEY_KEYS\"\n exit 1\nfi\n\n# Paso 4: Promover Valkey y redirigir tráfico\nvalkey-cli -h $VALKEY_HOST REPLICAOF NO ONE\n\n# Paso 5: Actualizar DNS/service discovery\n# (usando Consul, esto es una actualización de catálogo)\nconsul kv put \"cache/shard-${SHARD}/primary\" \"$VALKEY_HOST:6379\"\n```\n\nEl protocolo de replicación entre Redis y Valkey es compatible (Valkey puede replicar desde Redis y viceversa hasta el punto del fork). Esto fue lo que habilitó la migración sin downtime. El enfoque fue un shard por día durante dos semanas, monitoreando cada uno durante 24 horas antes de pasar al siguiente.\n\n### Los problemas complejos que Encontramos\n\n**1. Comportamiento distinto de ` maxmemory-policy `.** La evicción ` allkeys-lfu ` de Valkey tiene una curva de decaimiento de frecuencia levemente distinta a Redis 7.2. El cache hit rate cayó ~3% en un shard después de migrar. La solución fue tunear ` lfu-decay-time ` del default 1 a 3:\n\n```conf\nlfu-decay-time 3\n# Decaimiento de frecuencia más lento = mejor para identificar\n# keys realmente calientes vs. keys que tuvieron un burst de acceso\n```\n\n**2. Manejo de timeout en scripts Lua.** Un script Lua ocasionalmente tardaba \\>5 segundos en keyspaces grandes. Redis mata el script y devuelve BUSY. Valkey también lo mata, pero el formato del mensaje de error es levemente distinto, lo que rompió la lógica de retry que parseaba el string de error. No parseen mensajes de error. Usen códigos de error.\n\n**3. Versión del formato RDB.** Valkey introdujo RDB versión 12 para algunas de sus nuevas estructuras de datos. Si se necesita volver a Redis, no es posible cargar un archivo RDB generado por Valkey que use el formato nuevo. Es aconsejable mantener backups RDB compatibles con Redis durante el primer mes:\n\n```conf\n# Forzar compatibilidad RDB durante período de migración\nrdb-compat-version 11\n```\n\n## Análisis de Optimización de Memoria\n\nValkey 8.0 introdujo cambios en cómo se almacenan las estructuras de datos chicas. La codificación ` listpack ` (que reemplazó a ` ziplist ` en Redis 7) se optimizó aún más con mejor alineación de memoria y overhead reducido por entrada.\n\nSe midió el uso de memoria con datasets idénticos:\n\n```python\n# Script de test: poblar estructuras de datos idénticas\nimport valkey\nimport json\nimport random\nimport string\n\ndef random_string(n):\n return ''.join(random.choices(string.ascii_letters, k=n))\n\ndef populate(client, prefix, count=1_000_000):\n pipe = client.pipeline()\n for i in range(count):\n # Mix de tipos de datos\n pipe.set(f'{prefix}:str:{i}', random_string(64))\n pipe.hset(f'{prefix}:hash:{i}', mapping={\n 'field1': random_string(32),\n 'field2': str(random.randint(0, 100000)),\n 'field3': random_string(16),\n })\n pipe.zadd(f'{prefix}:zset:{i % 10000}',\n {random_string(12): random.random()})\n if i % 5000 == 0:\n pipe.execute()\n pipe = client.pipeline()\n pipe.execute()\n```\n\nUso de memoria para 1M de entradas de cada tipo:\n\n| Tipo de Dato | Redis 7.2 | Valkey 8.0 | Ahorro |\n| --- | --- | --- | --- |\n| Strings (valores 64B) | 89.2 MB | 87.4 MB | 2.0% |\n| Hashes (3 campos) | 142.7 MB | 131.3 MB | 8.0% |\n| Sorted Sets (100 miembros) | 167.4 MB | 158.9 MB | 5.1% |\n| Streams (1K entradas) | 203.1 MB | 189.6 MB | 6.6% |\n\nLos ahorros en hashes son los más impactantes porque la codificación listpack maneja mejor el caso de hashes chicos. El default de ` hash-max-listpack-entries ` es 128 en ambos, pero la implementación listpack de Valkey empaqueta las entradas más ajustadas.\n\nLa desfragmentación activa también es notablemente mejor. Después de 48 horas de escrituras y borrados sostenidos en una instancia de test:\n\n```bash\n# Verificar ratio de fragmentación\nvalkey-cli INFO memory | grep mem_fragmentation_ratio\n# Redis 7.2 después de 48h: mem_fragmentation_ratio:1.43\n# Valkey 8.0 después de 48h: mem_fragmentation_ratio:1.12\n```\n\nUn ratio de fragmentación de 1.43 significa que Redis usa 43% más memoria de la que los datos realmente requieren. Valkey lo mantuvo en 12%. En un dataset de 14TB, eso es la diferencia entre necesitar 20TB de RAM y necesitar 15.7TB. A precios de cloud, eso es dinero real, aproximadamente $2,400/mes.\n\n## Estado de las Librerías Cliente\n\nEsto importa más de lo que la mayoría de los artículos admiten. El ecosistema de librerías cliente determina si la migración es trivial o un dolor de cabeza.\n\n| Lenguaje | Librería | Estado |\n| --- | --- | --- |\n| Python | valkey-py | Producción, fork de redis-py |\n| Node.js | iovalkey | Producción, fork de ioredis |\n| Java | Jedis 5.x | Soporte nativo Valkey |\n| Go | go-valkey | Producción, diseño Valkey-first |\n| Rust | valkey-rs | Basado en redis-rs, funciona |\n| .NET | StackExchange.Redis | Funciona con Valkey (protocolo compatible) |\n\nUsando iovalkey en Node.js, la migración es cambiar un paquete y una config:\n\n```javascript\n// Antes\nimport Redis from 'ioredis';\nconst client = new Redis({\n host: 'redis-primary.internal',\n port: 6379,\n maxRetriesPerRequest: 3,\n});\n\n// Después\nimport { Valkey } from 'iovalkey';\nconst client = new Valkey({\n host: 'valkey-primary.internal',\n port: 6379,\n maxRetriesPerRequest: 3,\n // Habilitar RESP3 para respuestas tipadas\n protocol: 3,\n});\n```\n\n## ¿Deberías Migrar?\n\nAquí va una evaluación honesta después de ocho meses de uso en producción:\n\n**Migrar si:** se está corriendo Redis OSS, se desea I/O multi-threaded para workloads con muchas conexiones, la licencia SSPL te preocupa, o se desea mejor eficiencia de memoria en workloads pesados en hashes.\n\n**No migrar si:** depende de módulos Redis Stack (Search, JSON, TimeSeries, Graph), se está en Redis Enterprise con SLAs en los que confiás, o tu workload es de conexión única (no se va a ver diferencia).\n\n**Esperá si:** no se está seguro. Valkey no se va a ir a ningún lado, el respaldo de la Linux Foundation asegura longevidad, y la base de contribuidores está creciendo. Puede migrar en un año y el proceso solo va a ser más fluido.\n\nUn punto importante: enmarcar esto como una elección política pierde el foco. Valkey es técnicamente superior para workloads con muchas conexiones, mejor eficiencia de memoria, mejor threading, misma compatibilidad. Si Redis siguiera siendo BSD y tuviera estas features, la recomendación sería Redis. Pero no las tiene, y Valkey sí. Ahí termina el análisis.\n\n## Preguntas frecuentes\n\n### ¿Valkey es un reemplazo drop-in de Redis?\n\nPara Redis OSS 7.2.x, sí, compatible a nivel de protocolo, mismo set de comandos. Pero si usa módulos de Redis Stack (RedisJSON, RedisSearch, RedisTimeSeries), ese es son propietarios y no están disponibles en Valkey. Existen alternativas comunitarias pero no son idénticas.\n\n### ¿Cuál es la diferencia de performance entre Valkey y Redis?\n\nCon I/O multi-threaded habilitado, Valkey maneja 2-3x más operaciones por segundo en workloads con muchas conexiones. En benchmarks de conexión única, la performance es prácticamente idéntica. La brecha crece con la cantidad de conexiones.\n\n### ¿Debería migrar de Redis a Valkey?\n\nSi se está en Redis OSS y te preocupa el licenciamiento (Redis cambió a SSPL/RSAL), sí. Si se está en Redis Enterprise con soporte, el business case depende de tu escala y si se necesita módulos de Redis Stack.\n\n## Tips\n\n1. **Tip:** Antes de migrar, ejecutar ` valkey-cli --bigkeys --memkeys ` sobre tu dump de Redis. El I/O multi-threaded de Valkey brilla con muchas keys chicas pero puede empeorar con pocas hash keys gigantes (\\>50MB) por contención de threads en la serialización.\n2. **Tip:** Configurar ` io-threads 4 ` y ` io-threads-do-reads yes ` en tu config de Valkey. El default es single-threaded por compatibilidad, lo que significa que no ves ningún beneficio sobre Redis de entrada.\n3. **Tip:** Si usa clientes RESP2, pasar a RESP3 con ` HELLO 3 `, las respuestas tipadas eliminan la coerción de tipos del lado del cliente, lo que solo nos ahorró ~8% CPU en los servers de aplicación.\n4. **Tip:** Utilizar ` activedefrag yes ` con ` active-defrag-threshold-lower 10 ` en Valkey. Su desfragmentación es mediblemente mejor que Redis 7.x, especialmente después de workloads de escritura sostenidos.\n\n- valkey\n- redis\n- base-de-datos-en-memoria\n- resp3\n- performance\n- migración\n- io-multi-threaded\n- caching\n\n[Volver al Blog](<https://lucioduran.com/es/blog>)","headings":[{"level":1,"text":"Valkey vs Redis: Migrando 14TB de Datos en Producción, Lo Que la Documentación No Cubre","url":"https://lucioduran.com/es/blog/valkey-redis-fork-performance-analysis#title"},{"level":2,"text":"Por Qué Existe Valkey (La Versión Corta)","url":"https://lucioduran.com/es/blog/valkey-redis-fork-performance-analysis#por-qu-existe-valkey-la-versin-corta"},{"level":2,"text":"RESP3: El Protocolo que Nadie Usa (Pero Debería)","url":"https://lucioduran.com/es/blog/valkey-redis-fork-performance-analysis#resp3-el-protocolo-que-nadie-usa-pero-debera"},{"level":2,"text":"I/O Multi-Threaded: Donde Valkey Realmente Diverge","url":"https://lucioduran.com/es/blog/valkey-redis-fork-performance-analysis#io-multi-threaded-donde-valkey-realmente-diverge"},{"level":2,"text":"La Migración: 14TB en 12 Shards","url":"https://lucioduran.com/es/blog/valkey-redis-fork-performance-analysis#la-migracin-14tb-en-12-shards"},{"level":3,"text":"Los problemas complejos que Encontramos","url":"https://lucioduran.com/es/blog/valkey-redis-fork-performance-analysis#los-problemas-complejos-que-encontramos"},{"level":2,"text":"Análisis de Optimización de Memoria","url":"https://lucioduran.com/es/blog/valkey-redis-fork-performance-analysis#anlisis-de-optimizacin-de-memoria"},{"level":2,"text":"Estado de las Librerías Cliente","url":"https://lucioduran.com/es/blog/valkey-redis-fork-performance-analysis#estado-de-las-libreras-cliente"},{"level":2,"text":"¿Deberías Migrar?","url":"https://lucioduran.com/es/blog/valkey-redis-fork-performance-analysis#deberas-migrar"},{"level":2,"text":"Preguntas frecuentes","url":"https://lucioduran.com/es/blog/valkey-redis-fork-performance-analysis#questions"},{"level":3,"text":"¿Valkey es un reemplazo drop-in de Redis?","url":"https://lucioduran.com/es/blog/valkey-redis-fork-performance-analysis#question-1"},{"level":3,"text":"¿Cuál es la diferencia de performance entre Valkey y Redis?","url":"https://lucioduran.com/es/blog/valkey-redis-fork-performance-analysis#question-2"},{"level":3,"text":"¿Debería migrar de Redis a Valkey?","url":"https://lucioduran.com/es/blog/valkey-redis-fork-performance-analysis#question-3"},{"level":2,"text":"Tips","url":"https://lucioduran.com/es/blog/valkey-redis-fork-performance-analysis#article-tips"}],"sections":[{"heading":"Valkey vs Redis: Migrando 14TB de Datos en Producción, Lo Que la Documentación No Cubre","level":1,"url":"https://lucioduran.com/es/blog/valkey-redis-fork-performance-analysis","content":"Databases"},{"heading":"Valkey vs Redis: Migrando 14TB de Datos en Producción, Lo Que la Documentación No Cubre","level":1,"url":"https://lucioduran.com/es/blog/valkey-redis-fork-performance-analysis#title","content":"2026-02-0210 min lectura\n\nLucio Durán\nEngineering Manager & AI Solutions Architect\n\nTambién disponible en: [English](<https://lucioduran.com/blog/valkey-redis-fork-performance-analysis>)"},{"heading":"Por Qué Existe Valkey (La Versión Corta)","level":2,"url":"https://lucioduran.com/es/blog/valkey-redis-fork-performance-analysis#por-qu-existe-valkey-la-versin-corta","content":"Redis Labs cambió su licencia de BSD a una licencia dual SSPL/RSAL en marzo 2024. Esto hizo imposible que los proveedores cloud ofrezcan Redis manejado sin un acuerdo comercial. [AWS](<https://aws.com/>), Google, Oracle y otros respaldaron el fork [Valkey](<https://valkey.io/>) bajo la Linux Foundation con licencia BSD-3-Clause.\n\nMás allá de la política, la pregunta relevante es si el software es mejor. Las siguientes secciones examinan la ingeniería real."},{"heading":"RESP3: El Protocolo que Nadie Usa (Pero Debería)","level":2,"url":"https://lucioduran.com/es/blog/valkey-redis-fork-performance-analysis#resp3-el-protocolo-que-nadie-usa-pero-debera","content":"RESP3 (Redis Serialization Protocol v3) se introdujo en Redis 6 pero casi nadie lo usa porque RESP2 sigue funcionando y la mayoría de las librerías de cliente lo usan por defecto. Esto es un error.\n\nRESP3 introduce respuestas tipadas. En RESP2, todo es o un string, integer, array o error. Tu librería cliente tiene que adivinar tipos:\n\n```\n# Respuesta RESP2 a HGETALL\n*4\n$4\nname\n$5\nLucio\n$3\nage\n$2\n38\n\n# El cliente tiene que saber que elementos alternos\n# forman pares key-value y que \"38\" probablemente\n# debería ser un integer\n```\n\n```\n# Respuesta RESP3 a HGETALL\n%2\n$4\nname\n$5\nLucio\n$3\nage\n:38\n\n# El prefijo % significa \"mapa con 2 entradas\"\n# El prefijo : significa \"esto es un integer\"\n# No hay que adivinar nada\n```\n\nEl impacto práctico es más grande de lo que parece. En servicios Node.js usando ioredis, pasar a RESP3 elimina un montón de llamadas a ` parseInt() ` y ` JSON.parse() ` del lado de la aplicación. El uso de CPU en los servers de app puede bajar ~8% en el hot path, no porque el protocolo sea más rápido por la red, sino porque dejamos de hacer coerción de tipos redundante.\n\nPara habilitar RESP3 en una conexión existente:\n\n```python\n# Python con valkey-py (fork de redis-py)\nimport valkey\n\nclient = valkey.Valkey(\n host='valkey-primary.internal',\n port=6379,\n protocol=3 # Esto manda HELLO 3 al conectar\n)\n\n# Ahora las respuestas son nativamente tipadas\nresult = client.hgetall('user:1001')\n# Devuelve: {'name': 'Lucio', 'age': 38}\n# age ya es un int, no b'38'\n```"},{"heading":"I/O Multi-Threaded: Donde Valkey Realmente Diverge","level":2,"url":"https://lucioduran.com/es/blog/valkey-redis-fork-performance-analysis#io-multi-threaded-donde-valkey-realmente-diverge","content":"Redis tiene ` io-threads ` desde la versión 6, pero estaba limitado a operaciones de escritura y se sentía como algo puesto a último momento. Valkey llevó esto más lejos con threading tanto de lectura como escritura, y la implementación es genuinamente distinta.\n\nLa arquitectura:\n\n```\n Thread Principal\n ┌──────────┐\n │ Ejecución│\n │ de │\n │ Comandos │\n │ (single) │\n └────┬─────┘\n │\n ┌──────────┼──────────┐\n │ │ │\n ┌────┴───┐ ┌───┴────┐ ┌──┴─────┐\n │ I/O │ │ I/O │ │ I/O │\n │Thread 1│ │Thread 2│ │Thread 3│\n │ read/ │ │ read/ │ │ read/ │\n │ write │ │ write │ │ write │\n └────────┘ └────────┘ └────────┘\n```\n\nLa ejecución de comandos sigue siendo single-threaded (esto es fundamental para el modelo de consistencia de Valkey/Redis, no se necesitan locks). Pero el parsing de I/O y la serialización de respuestas pasan en paralelo entre threads. Aquí va una configuración que funciona bien en instancias de 8 cores:\n\n```conf\n# valkey.conf\nio-threads 4\nio-threads-do-reads yes\n\n# No configurar io-threads más alto que tu core count menos 2\n# El thread principal + tareas de background necesitan CPU\n# 4 threads en 8 cores es típicamente el punto óptimo\n\n# Aumentar el backlog para workloads con muchas conexiones\ntcp-backlog 4096\n```\n\nEsto se benchmarkeó sistemáticamente usando ` valkey-benchmark ` con distintas cantidades de conexiones:\n\n```bash\n# Conexión única (no se espera beneficio del threading)\nvalkey-benchmark -h 127.0.0.1 -p 6379 -c 1 -n 1000000 \\\n -t set,get -d 256 --threads 1\n\n# 200 conexiones (donde el threading importa)\nvalkey-benchmark -h 127.0.0.1 -p 6379 -c 200 -n 5000000 \\\n -t set,get -d 256 --threads 4\n\n# 1000 conexiones (stress test)\nvalkey-benchmark -h 127.0.0.1 -p 6379 -c 1000 -n 10000000 \\\n -t set,get -d 256 --threads 8\n```\n\nResultados en un r7g.2xlarge (8 vCPU, 64GB):\n\n| Conexiones | Redis 7.2 (ops/s) | Valkey 8.0 1-thread (ops/s) | Valkey 8.0 4-thread (ops/s) |\n| --- | --- | --- | --- |\n| 1 | 142,000 | 144,000 | 143,000 |\n| 50 | 398,000 | 405,000 | 612,000 |\n| 200 | 445,000 | 451,000 | 891,000 |\n| 500 | 462,000 | 468,000 | 1,024,000 |\n| 1000 | 471,000 | 475,000 | 1,143,000 |\n\nCon 1 conexión, sin diferencia. Con 1000 conexiones, Valkey con 4 threads de I/O entrega 2.4x el throughput. No es magia, es simplemente que la lectura/escritura de sockets y la serialización de respuestas están paralelizadas mientras la ejecución de comandos sigue serializada."},{"heading":"La Migración: 14TB en 12 Shards","level":2,"url":"https://lucioduran.com/es/blog/valkey-redis-fork-performance-analysis#la-migracin-14tb-en-12-shards","content":"El setup: 12 clusters Redis (cada uno con un primary + 2 réplicas) manejando datos de sesión, feature flags, rate limiting y un pipeline de analytics en tiempo real. Dataset total: ~14TB entre todos los shards.\n\nLa estrategia de migración fue reemplazo rolling sin downtime:\n\n```bash\n#!/bin/bash\n# Versión simplificada de nuestro script de migración\n# La versión real tenía manejo de errores, rollback y hooks de monitoreo\n\nSHARD=$1\nREDIS_HOST=\"redis-${SHARD}.internal\"\nVALKEY_HOST=\"valkey-${SHARD}.internal\"\n\n# Paso 1: Configurar Valkey como réplica de Redis\nvalkey-cli -h $VALKEY_HOST \\\n REPLICAOF $REDIS_HOST 6379\n\n# Paso 2: Esperar a que termine el sync\nwhile true; do\n STATUS=$(valkey-cli -h $VALKEY_HOST INFO replication \\\n | grep master_sync_in_progress)\n if [[ $STATUS == *\"0\"* ]]; then\n echo \"Sync completo para shard $SHARD\"\n break\n fi\n sleep 5\ndone\n\n# Paso 3: Verificar integridad de datos\nREDIS_KEYS=$(redis-cli -h $REDIS_HOST DBSIZE | awk '{print $2}')\nVALKEY_KEYS=$(valkey-cli -h $VALKEY_HOST DBSIZE | awk '{print $2}')\nDIFF=$((VALKEY_KEYS - REDIS_KEYS))\n\nif [ ${DIFF#-} -gt 100 ]; then\n echo \"ERROR: Diferencia de keys: Redis=$REDIS_KEYS Valkey=$VALKEY_KEYS\"\n exit 1\nfi\n\n# Paso 4: Promover Valkey y redirigir tráfico\nvalkey-cli -h $VALKEY_HOST REPLICAOF NO ONE\n\n# Paso 5: Actualizar DNS/service discovery\n# (usando Consul, esto es una actualización de catálogo)\nconsul kv put \"cache/shard-${SHARD}/primary\" \"$VALKEY_HOST:6379\"\n```\n\nEl protocolo de replicación entre Redis y Valkey es compatible (Valkey puede replicar desde Redis y viceversa hasta el punto del fork). Esto fue lo que habilitó la migración sin downtime. El enfoque fue un shard por día durante dos semanas, monitoreando cada uno durante 24 horas antes de pasar al siguiente."},{"heading":"Los problemas complejos que Encontramos","level":3,"url":"https://lucioduran.com/es/blog/valkey-redis-fork-performance-analysis#los-problemas-complejos-que-encontramos","content":"**1. Comportamiento distinto de ` maxmemory-policy `.** La evicción ` allkeys-lfu ` de Valkey tiene una curva de decaimiento de frecuencia levemente distinta a Redis 7.2. El cache hit rate cayó ~3% en un shard después de migrar. La solución fue tunear ` lfu-decay-time ` del default 1 a 3:\n\n```conf\nlfu-decay-time 3\n# Decaimiento de frecuencia más lento = mejor para identificar\n# keys realmente calientes vs. keys que tuvieron un burst de acceso\n```\n\n**2. Manejo de timeout en scripts Lua.** Un script Lua ocasionalmente tardaba \\>5 segundos en keyspaces grandes. Redis mata el script y devuelve BUSY. Valkey también lo mata, pero el formato del mensaje de error es levemente distinto, lo que rompió la lógica de retry que parseaba el string de error. No parseen mensajes de error. Usen códigos de error.\n\n**3. Versión del formato RDB.** Valkey introdujo RDB versión 12 para algunas de sus nuevas estructuras de datos. Si se necesita volver a Redis, no es posible cargar un archivo RDB generado por Valkey que use el formato nuevo. Es aconsejable mantener backups RDB compatibles con Redis durante el primer mes:\n\n```conf\n# Forzar compatibilidad RDB durante período de migración\nrdb-compat-version 11\n```"},{"heading":"Análisis de Optimización de Memoria","level":2,"url":"https://lucioduran.com/es/blog/valkey-redis-fork-performance-analysis#anlisis-de-optimizacin-de-memoria","content":"Valkey 8.0 introdujo cambios en cómo se almacenan las estructuras de datos chicas. La codificación ` listpack ` (que reemplazó a ` ziplist ` en Redis 7) se optimizó aún más con mejor alineación de memoria y overhead reducido por entrada.\n\nSe midió el uso de memoria con datasets idénticos:\n\n```python\n# Script de test: poblar estructuras de datos idénticas\nimport valkey\nimport json\nimport random\nimport string\n\ndef random_string(n):\n return ''.join(random.choices(string.ascii_letters, k=n))\n\ndef populate(client, prefix, count=1_000_000):\n pipe = client.pipeline()\n for i in range(count):\n # Mix de tipos de datos\n pipe.set(f'{prefix}:str:{i}', random_string(64))\n pipe.hset(f'{prefix}:hash:{i}', mapping={\n 'field1': random_string(32),\n 'field2': str(random.randint(0, 100000)),\n 'field3': random_string(16),\n })\n pipe.zadd(f'{prefix}:zset:{i % 10000}',\n {random_string(12): random.random()})\n if i % 5000 == 0:\n pipe.execute()\n pipe = client.pipeline()\n pipe.execute()\n```\n\nUso de memoria para 1M de entradas de cada tipo:\n\n| Tipo de Dato | Redis 7.2 | Valkey 8.0 | Ahorro |\n| --- | --- | --- | --- |\n| Strings (valores 64B) | 89.2 MB | 87.4 MB | 2.0% |\n| Hashes (3 campos) | 142.7 MB | 131.3 MB | 8.0% |\n| Sorted Sets (100 miembros) | 167.4 MB | 158.9 MB | 5.1% |\n| Streams (1K entradas) | 203.1 MB | 189.6 MB | 6.6% |\n\nLos ahorros en hashes son los más impactantes porque la codificación listpack maneja mejor el caso de hashes chicos. El default de ` hash-max-listpack-entries ` es 128 en ambos, pero la implementación listpack de Valkey empaqueta las entradas más ajustadas.\n\nLa desfragmentación activa también es notablemente mejor. Después de 48 horas de escrituras y borrados sostenidos en una instancia de test:\n\n```bash\n# Verificar ratio de fragmentación\nvalkey-cli INFO memory | grep mem_fragmentation_ratio\n# Redis 7.2 después de 48h: mem_fragmentation_ratio:1.43\n# Valkey 8.0 después de 48h: mem_fragmentation_ratio:1.12\n```\n\nUn ratio de fragmentación de 1.43 significa que Redis usa 43% más memoria de la que los datos realmente requieren. Valkey lo mantuvo en 12%. En un dataset de 14TB, eso es la diferencia entre necesitar 20TB de RAM y necesitar 15.7TB. A precios de cloud, eso es dinero real, aproximadamente $2,400/mes."},{"heading":"Estado de las Librerías Cliente","level":2,"url":"https://lucioduran.com/es/blog/valkey-redis-fork-performance-analysis#estado-de-las-libreras-cliente","content":"Esto importa más de lo que la mayoría de los artículos admiten. El ecosistema de librerías cliente determina si la migración es trivial o un dolor de cabeza.\n\n| Lenguaje | Librería | Estado |\n| --- | --- | --- |\n| Python | valkey-py | Producción, fork de redis-py |\n| Node.js | iovalkey | Producción, fork de ioredis |\n| Java | Jedis 5.x | Soporte nativo Valkey |\n| Go | go-valkey | Producción, diseño Valkey-first |\n| Rust | valkey-rs | Basado en redis-rs, funciona |\n| .NET | StackExchange.Redis | Funciona con Valkey (protocolo compatible) |\n\nUsando iovalkey en Node.js, la migración es cambiar un paquete y una config:\n\n```javascript\n// Antes\nimport Redis from 'ioredis';\nconst client = new Redis({\n host: 'redis-primary.internal',\n port: 6379,\n maxRetriesPerRequest: 3,\n});\n\n// Después\nimport { Valkey } from 'iovalkey';\nconst client = new Valkey({\n host: 'valkey-primary.internal',\n port: 6379,\n maxRetriesPerRequest: 3,\n // Habilitar RESP3 para respuestas tipadas\n protocol: 3,\n});\n```"},{"heading":"¿Deberías Migrar?","level":2,"url":"https://lucioduran.com/es/blog/valkey-redis-fork-performance-analysis#deberas-migrar","content":"Aquí va una evaluación honesta después de ocho meses de uso en producción:\n\n**Migrar si:** se está corriendo Redis OSS, se desea I/O multi-threaded para workloads con muchas conexiones, la licencia SSPL te preocupa, o se desea mejor eficiencia de memoria en workloads pesados en hashes.\n\n**No migrar si:** depende de módulos Redis Stack (Search, JSON, TimeSeries, Graph), se está en Redis Enterprise con SLAs en los que confiás, o tu workload es de conexión única (no se va a ver diferencia).\n\n**Esperá si:** no se está seguro. Valkey no se va a ir a ningún lado, el respaldo de la Linux Foundation asegura longevidad, y la base de contribuidores está creciendo. Puede migrar en un año y el proceso solo va a ser más fluido.\n\nUn punto importante: enmarcar esto como una elección política pierde el foco. Valkey es técnicamente superior para workloads con muchas conexiones, mejor eficiencia de memoria, mejor threading, misma compatibilidad. Si Redis siguiera siendo BSD y tuviera estas features, la recomendación sería Redis. Pero no las tiene, y Valkey sí. Ahí termina el análisis."},{"heading":"Preguntas frecuentes","level":2,"url":"https://lucioduran.com/es/blog/valkey-redis-fork-performance-analysis#questions","content":""},{"heading":"¿Valkey es un reemplazo drop-in de Redis?","level":3,"url":"https://lucioduran.com/es/blog/valkey-redis-fork-performance-analysis#question-1","content":"Para Redis OSS 7.2.x, sí, compatible a nivel de protocolo, mismo set de comandos. Pero si usa módulos de Redis Stack (RedisJSON, RedisSearch, RedisTimeSeries), ese es son propietarios y no están disponibles en Valkey. Existen alternativas comunitarias pero no son idénticas."},{"heading":"¿Cuál es la diferencia de performance entre Valkey y Redis?","level":3,"url":"https://lucioduran.com/es/blog/valkey-redis-fork-performance-analysis#question-2","content":"Con I/O multi-threaded habilitado, Valkey maneja 2-3x más operaciones por segundo en workloads con muchas conexiones. En benchmarks de conexión única, la performance es prácticamente idéntica. La brecha crece con la cantidad de conexiones."},{"heading":"¿Debería migrar de Redis a Valkey?","level":3,"url":"https://lucioduran.com/es/blog/valkey-redis-fork-performance-analysis#question-3","content":"Si se está en Redis OSS y te preocupa el licenciamiento (Redis cambió a SSPL/RSAL), sí. Si se está en Redis Enterprise con soporte, el business case depende de tu escala y si se necesita módulos de Redis Stack."},{"heading":"Tips","level":2,"url":"https://lucioduran.com/es/blog/valkey-redis-fork-performance-analysis#article-tips","content":"1. **Tip:** Antes de migrar, ejecutar ` valkey-cli --bigkeys --memkeys ` sobre tu dump de Redis. El I/O multi-threaded de Valkey brilla con muchas keys chicas pero puede empeorar con pocas hash keys gigantes (\\>50MB) por contención de threads en la serialización.\n2. **Tip:** Configurar ` io-threads 4 ` y ` io-threads-do-reads yes ` en tu config de Valkey. El default es single-threaded por compatibilidad, lo que significa que no ves ningún beneficio sobre Redis de entrada.\n3. **Tip:** Si usa clientes RESP2, pasar a RESP3 con ` HELLO 3 `, las respuestas tipadas eliminan la coerción de tipos del lado del cliente, lo que solo nos ahorró ~8% CPU en los servers de aplicación.\n4. **Tip:** Utilizar ` activedefrag yes ` con ` active-defrag-threshold-lower 10 ` en Valkey. Su desfragmentación es mediblemente mejor que Redis 7.x, especialmente después de workloads de escritura sostenidos.\n\n- valkey\n- redis\n- base-de-datos-en-memoria\n- resp3\n- performance\n- migración\n- io-multi-threaded\n- caching\n\n[Volver al Blog](<https://lucioduran.com/es/blog>)"}],"links":[{"text":"English","url":"https://lucioduran.com/blog/valkey-redis-fork-performance-analysis"},{"text":"AWS","url":"https://aws.com/"},{"text":"Valkey","url":"https://valkey.io/"},{"text":"Volver al Blog","url":"https://lucioduran.com/es/blog"}],"structuredData":[{"@context":"https://schema.org","@graph":[{"@type":"BlogPosting","@id":"https://lucioduran.com/es/blog/valkey-redis-fork-performance-analysis#article","mainEntityOfPage":{"@type":"WebPage","@id":"https://lucioduran.com/es/blog/valkey-redis-fork-performance-analysis"},"headline":"Valkey vs Redis: Migrando 14TB de Datos en Producción, Lo Que la Documentación No Cubre","description":"Análisis del I/O multi-threaded de Valkey, el protocolo RESP3 y las optimizaciones de memoria. Incluye una migración real desde Redis 7.2, metodología de benchmarks y los problemas complejos encontrados en producción.","datePublished":"2026-02-02","author":{"@type":"Person","@id":"https://lucioduran.com/#person","name":"Lucio Durán","url":"https://lucioduran.com"},"publisher":{"@type":"Person","@id":"https://lucioduran.com/#person","name":"Lucio Durán","url":"https://lucioduran.com"},"image":"https://lucioduran.com/favicons/og-default.png","url":"https://lucioduran.com/es/blog/valkey-redis-fork-performance-analysis","inLanguage":"es","isPartOf":{"@id":"https://lucioduran.com/blog#blog"},"articleSection":"Databases","keywords":"valkey, redis, base-de-datos-en-memoria, resp3, performance, migración, io-multi-threaded, caching","wordCount":1771,"timeRequired":"PT10M","workTranslation":[{"@type":"BlogPosting","inLanguage":"en","url":"https://lucioduran.com/blog/valkey-redis-fork-performance-analysis"}]},{"@type":"BreadcrumbList","itemListElement":[{"@type":"ListItem","position":1,"name":"Inicio","item":"https://lucioduran.com/"},{"@type":"ListItem","position":2,"name":"Blog","item":"https://lucioduran.com/es/blog"},{"@type":"ListItem","position":3,"name":"Valkey vs Redis: Migrando 14TB de Datos en Producción, Lo Que la Documentación No Cubre","item":"https://lucioduran.com/es/blog/valkey-redis-fork-performance-analysis"}]},{"@type":"FAQPage","mainEntity":[{"@type":"Question","name":"¿Valkey es un reemplazo drop-in de Redis?","acceptedAnswer":{"@type":"Answer","text":"Para Redis OSS 7.2.x, sí, compatible a nivel de protocolo, mismo set de comandos. Pero si usa módulos de Redis Stack (RedisJSON, RedisSearch, RedisTimeSeries), ese es son propietarios y no están disponibles en Valkey. Existen alternativas comunitarias pero no son idénticas."}},{"@type":"Question","name":"¿Cuál es la diferencia de performance entre Valkey y Redis?","acceptedAnswer":{"@type":"Answer","text":"Con I/O multi-threaded habilitado, Valkey maneja 2-3x más operaciones por segundo en workloads con muchas conexiones. En benchmarks de conexión única, la performance es prácticamente idéntica. La brecha crece con la cantidad de conexiones."}},{"@type":"Question","name":"¿Debería migrar de Redis a Valkey?","acceptedAnswer":{"@type":"Answer","text":"Si se está en Redis OSS y te preocupa el licenciamiento (Redis cambió a SSPL/RSAL), sí. Si se está en Redis Enterprise con soporte, el business case depende de tu escala y si se necesita módulos de Redis Stack."}}]}]}],"contentHash":"b619afc4016a75601eb013d0960b1db8bf64191110fe9232b4853ab53d3a5768","provenance":{"method":"Deterministic serialization of the server-rendered main element","source":"https://lucioduran.com/es/blog/valkey-redis-fork-performance-analysis","hashAlgorithm":"sha256","hashScope":"JSON document fields before contentHash and provenance","sourceHTMLBytes":70405,"contentBytes":14675}}
