Apariencia
0063. Redis se configura con una connection string (REDIS_URL), no con host y puerto
Estado
Aceptada
Contexto
Desde permissions-redis-cache, RedisService se construía con { host, port } leídos de REDIS_HOST y REDIS_PORT. Funcionaba perfecto en desarrollo, donde el Redis del docker-compose no lleva password ni TLS.
Al preparar el primer despliegue apareció el problema: ningún Redis gestionado acepta conexiones sin autenticación, y varios (Upstash entre ellos) exigen TLS. Ni la password ni el TLS son expresables en un modelo host/puerto — habría que agregar REDIS_PASSWORD, REDIS_TLS, y probablemente más adelante REDIS_USERNAME y REDIS_DB, replicando a mano lo que el estándar ya resuelve.
Además, la validación de entorno es fail-fast (ADR-0008): con las variables viejas requeridas, el contenedor no arrancaba en absoluto en producción.
Decisión
Una sola variable: REDIS_URL
Se reemplazan REDIS_HOST y REDIS_PORT por REDIS_URL, que ioredis parsea nativamente y que es el formato que todos los proveedores entregan:
redis://localhost:6379 # dev, sin auth
redis://default:password@host:6379 # gestionado, sin TLS
rediss://default:password@host:6379 # gestionado, con TLSConserva un default (redis://localhost:6379) para no romper el .env ni el .env.test de nadie, ni la suite e2e.
REDIS_FAMILY opcional para redes IPv6-only
La red privada de Railway es IPv6-only, y ioredis resuelve DNS en IPv4 por defecto: redis.railway.internal simplemente no resuelve. Se agrega REDIS_FAMILY (opcional, valores 4 o 6) que se pasa a ioredis solo si está definida.
Se deja como variable de entorno y no hardcodeada, porque es una característica de la red donde se despliega, no del código. Upstash, por ejemplo, se accede por URL pública con TLS y no la necesita.
Es el mismo problema IPv4/IPv6 que ya había aparecido dos veces en este proyecto: en el CI del backend y en el bind de los tests e2e (ADR-0040). La tercera vez conviene dejarlo escrito.
La política de fallback no cambia
RedisService mantiene intactos commandTimeout, maxRetriesPerRequest, enableOfflineQueue: false y su retryStrategy. Redis sigue siendo una optimización que nunca tumba la aplicación.
Consecuencias
Migrar de proveedor de Redis es cambiar una variable. Es parte de por qué la migración a Upstash descrita en ADR-0062 no requiere tocar código.
REDIS_FAMILYmal configurada falla en silencio, y esto es lo más importante de este ADR. Si falta en Railway,ioredisno resuelve el host,RedisServicedegrada a PostgreSQL según su diseño y solo emite un warning con throttle. La aplicación responde con normalidad, pero:- cada request resuelve permisos con una query a la base en vez de leer del cache;
- la idempotencia del outbox offline deja de funcionar (ADR-0055), porque se apoya en Redis.
Por eso la verificación post-despliegue exige buscar
Conectado a Redisen los logs de forma explícita: es un fallo que no se manifiesta como fallo.Quien clone el repo tras este cambio debe actualizar su
.envlocal. El default hace que no sea urgente en desarrollo.