Feature flags en Next.js: despliegues seguros, rollbacks sin drama
Qué son los feature flags, cómo encajan en Next.js, experiencia real con LaunchDarkly, cómo evitar que acumulen deuda técnica, y un repaso de las principales alternativas.
Un feature flag (o feature toggle) es una decisión que toma tu app en tiempo de ejecución: "¿esta parte del producto está activa para este usuario, en este entorno, ahora mismo?" No reemplaza un buen diseño ni los tests, pero cambia qué tan seguro y gradual puedes mover código a producción.
Por qué los uso en cada feature nuevo
Cuando desarrollo algo nuevo, lo envuelvo en un flag salvo que sea trivial y reversible en segundos. Los motivos son prácticos:
- Rollback sin redeploy: si algo sale mal en producción, apagas el flag y vuelves al comportamiento anterior sin esperar un pipeline completo. El fix puede llegar después, con calma.
- Rollout por audiencia: puedes mostrar un cambio solo a un cliente, a un porcentaje de usuarios, a un país, o a beta testers, mientras el resto sigue en la versión estable.
- Menos miedo al merge: el código llega a
maindetrás del flag, lo que reduce ramas largas y conflictos grandes.
Cómo evitar que los flags acumulen deuda técnica
Los flags que nadie retira se convierten en condiciones muertas que nadie se atreve a tocar. El proceso que me ha funcionado es simple: por cada flag que creo, abro un ticket de tech debt y agrego un TODO en el código con el link a ese ticket.
// TODO: eliminar flag cuando el rollout esté completo
// Tech debt: https://linear.app/tu-equipo/issue/ENG-123
if (featureFlags.isEnabled('nuevo-checkout', user)) {
mostrarNuevoCheckout();
}
Así, en cualquier sesión de limpieza del backlog, la tarea aparece y no se olvida. No requiere disciplina heroica — solo un proceso consistente.
Cómo encajan en Next.js
El reto con Next.js es coordinar servidor y cliente. El HTML que genera el servidor y lo que hidrata React deben contar la misma historia si el flag afecta la Interfaz de Usuario (IU) visible o datos importantes.
- Server Components / RSC: evalúa el flag en el servidor cuando el resultado debe influir en el HTML inicial o en datos sensibles. Un flag "por usuario" implica contenido dinámico — no puedes usar caché estático para eso.
- Client Components: útil para IU que cambia después de hidratar o para detalles que no afectan el primer render. Evita que servidor y cliente muestren cosas distintas.
- Middleware: encaja para redirecciones tempranas o experimentos de enrutamiento. No es el lugar para lógica de negocio compleja.
- Identidad del usuario: para segmentación por cliente necesitas un identificador estable — cuenta, tenant, cookie firmada. Sin identidad, solo puedes hacer porcentajes anónimos o reglas por entorno.
LaunchDarkly: experiencia real
He trabajado bastante con LaunchDarkly y la integración con React ha sido muy buena: los hooks y componentes encajan bien con el modelo mental de "leer estado remoto y re-renderizar". Su soporte para backend (Node, otros runtimes) también es sólido, lo que permite tomar la misma decisión de flag en API routes y servicios con reglas de targeting alineadas.
Lo que más uso en el día a día:
- Encender y apagar un cambio desde el panel, sin tocar código.
- Variantes y A/B testing: no solo booleanos — útil cuando quieres medir el impacto de un cambio, no solo ocultarlo.
- Tests E2E con Playwright: puedes forzar flags a valores conocidos para que las rutas críticas no dependan de un experimento aleatorio, eliminando el flakiness.
Otras opciones
Según tu presupuesto, si prefieres self-hosting o qué tan acoplado quieres estar a tu plataforma, hay buenas alternativas:
- Vercel Flags SDK: integración nativa con Next.js, soporta precompute para páginas estáticas. Documentación.
- Statsig: buenas herramientas para rollouts y experimentación. Guía.
- ConfigCat: tutorial paso a paso con SSR. Tutorial.
- Flagsmith: open source, con guías para App Router. Ejemplo en DEV.
- GrowthBook, Unleash, Flipt: otras opciones open source con distintos niveles de complejidad.
- Variables de entorno: para casos simples donde el flag no cambia en tiempo de ejecución, a veces es suficiente.
La herramienta importa menos que tener un contrato claro: quién evalúa el flag, con qué identidad, y cómo se observa el impacto en logs o analytics.
Un poco de historia: cómo se controlaban los releases antes
Los feature flags parecen obvios hoy. Pero antes de que existieran plataformas dedicadas, los equipos igual necesitaban formas de esconder trabajo incompleto y reducir el riesgo al hacer release. Todo era más manual y más frágil.
Cuando deployar era lo mismo que hacer release
Si estaba en producción, los usuarios podían verlo. Cada deploy era un riesgo, los bugs llegaban directo a los usuarios, y hacer rollback significaba redesplegar. Esa presión empujó a los equipos a buscar formas de esconder trabajo incompleto.
Ramas de larga vida
La solución más común: no hacer merge hasta que estuviera listo. Los engineers trabajaban en aislamiento durante días o semanas, y mergeaban solo cuando el feature estaba completo. El resultado fue conflictos de merge dolorosos y problemas de integración descubiertos tarde. En lugar de reducir el riesgo, este enfoque casi siempre solo lo postergaba.
Variables de entorno y flags en base de datos
Algunos equipos empezaron a agregar condicionales básicos con variables de entorno — un paso adelante, pero que requería redeploy para cambiar cualquier cosa. El siguiente nivel fue usar la base de datos para controlar features dinámicamente: sin redeploy, con targeting básico. Pero sin UI, sin logs de auditoría, y con lógica esparcida por todo el código. Muchas empresas todavía corren versiones de esto hoy.
Canary releases a nivel de infraestructura
Repartir el tráfico entre la versión vieja y la nueva en distintos servidores funcionaba, pero sin precisión: no podías elegir por usuario ni cortar el cambio al momento.
Lo que cambió
En todos esos enfoques aparecían los mismos problemas: sin control en tiempo real, releases de todo o nada, rollbacks lentos. Lo que cambiaron las plataformas modernas no fue el concepto — la lógica condicional ya existía. Lo que cambió fue la abstracción y la disciplina alrededor de eso. El deploy se volvió rutina. El release se volvió una decisión.
Resumen
Los feature flags son una palanca operativa: despliegues más seguros, rollbacks rápidos y pruebas con audiencias reales. Con el proceso de tech debt ticket + TODO en código, además, evitas que se conviertan en deuda que nadie retira. LaunchDarkly ha sido una opción sólida en mi experiencia, pero el ecosistema es amplio — elige según tu equipo, tus requisitos y cómo quieres monitorear el impacto en producción.