Qué son los feature flags: Despliegue progresivo SRE
Resumen
Qué son los feature flags y por qué cambian el modelo de riesgo en despliegues. Feature flags son condicionales en tu código que controlan qué flujo ejecuta cada usuario sin una nueva build. El contrato que establecen es preciso: despliegue y release son dos eventos separados. En equipos con despliegue continuo a escala, ese contrato es fundamental.
¿Qué son los feature flags? Son condicionales en tu código de aplicación que controlan qué rutas se ejecutan para un usuario, sesión o entorno específico, sin compilar una nueva build. Un flag llamado new_checkout_flow configurado en false para el 99% de tu base de usuarios significa que ese código fue desplegado hace dos semanas. Simplemente aún no lo has activado. El contrato que establecen es preciso: despliegue y release se convierten en dos eventos separados. Para cualquier equipo que hace despliegue continuo a escala, ese contrato es insustituible.
Despliegue y Release No Son el Mismo Evento
La mayoría de equipos aprenden esta distinción después de un rollout fallido. Una característica se lanza el martes por la tarde, algo en el trace de solicitudes empieza a comportarse diferente el miércoles por la mañana, y cuando alguien abre una investigación el diff cubre cuatro commits y dos límites de servicios. Atribuir causalidad en ese escenario es genuinamente difícil.
Los feature flags fuerzan precisión. Cuando el código detrás de un flag se mergea y despliega, permanece inerte en producción. Confirmas que el despliegue fue exitoso, observas métricas base durante algunas horas o días, y verificas que nada se degradó. Luego activas el flag para el 1% del tráfico. Ahora tienes una variable única y atribuible. Si la tasa de error sube en el path marcado, no estás debuggeando un diff de código. Estás toggling un valor de configuración.
Esa separación no es principalmente un argumento de velocidad, es un argumento de blast radius. Un release que afecta al 1% de sesiones que sale mal es recuperable en minutos. Un release que afecta al 100% que sale mal es un incidente mayor.
El mecanismo en sí es directo. En TypeScript, una evaluación de flag se ve aproximadamente así:
const showNewCheckoutFlow = flagClient.variation(
'new_checkout_flow',
{ userKey: session.userId, custom: { plan: user.plan } },
false // default si el servicio de flags es inaccesible
);
if (showNewCheckoutFlow) {
return renderNewFlow(cart);
}
return renderLegacyFlow(cart);El default false no es una formalidad. Es el comportamiento que tus usuarios reciben si el servicio de evaluación de flags tiene una partición de red. Define deliberadamente, no por accidente.
Los Cuatro Tipos de Feature Flags Que Importan en Producción
No todos los feature flags sirven el mismo propósito operacional. Tratarlos idénticamente en tu base de código y tooling de gestión es un camino confiable hacia la confusión durante incidentes y acumulación de flag debt.
Release flags cierran nuevas características durante desarrollo y rollout. Se espera que sean temporales: creados cuando comienza el trabajo en una rama de feature, removidos una vez que la característica alcanza el 100% de usuarios y el equipo ha confirmado estabilidad. Los release flags sin fecha de remoción y sin propietario asignado se vuelven muebles permanentes en tu base de código.
Experiment flags potencian A/B tests y experimentos multivariados. Se vinculan a identificadores de cohorte analítica y su ciclo de vida está limitado por el experimento. Cuando el experimento concluye, el flag se va con él. El error común: mantener la variante ganadora detrás del flag indefinidamente, razonando que la remoción "no es urgente". Dos años después, el flag de experimento es parte de la ruta crítica y nadie recuerda cuál variante está activa.
Ops flags son kill switches y circuit breakers. A diferencia de los release flags, están diseñados para ser infraestructura permanente. Un flag disable_ml_recommendations que te permite evitar una capa de inferencia ML lenta cuando su SLO se degrada es algo que quieres disponible a las 3am sin leer documentación. Estos flags deben evaluarse localmente, tener un fallback bien documentado, y ser testeados regularmente en operaciones normales, no descubiertos bajo presión.
Permission flags controlan acceso por tier de usuario, plan de cuenta, o cohorte beta. Están diseñados para ser long-lived. El riesgo de confusión: los permission flags a menudo lucen como release flags para quien no conoce el historial. Una convención de naming clara importa más aquí que en cualquier otro lado.

Un Rollout Porcentual Sin SLO Gate Es Solo Un Despliegue Lento
Aquí es donde la mayoría de implementaciones de feature flags se quedan cortas. El equipo de plataforma configura un cronograma de rollout: 1% el lunes, 5% martes, 25% miércoles, 100% viernes. Lo documentan, lo comparten con stakeholders, y lo llaman delivery progresivo.
Pero "progresivo" sin una condición de validación en cada paso es riesgo diferido, no riesgo reducido. El dial de porcentaje controla exposición. No valida seguridad.
Lo que hace un rollout staged operacionalmente significativo es el SLO gate entre cada etapa. Antes de avanzar del 5% al 25%, algo debe responder: ¿está la tasa de error en el path marcado dentro del presupuesto SLO? ¿Está el p99 latency dentro de la misma banda que el grupo control? ¿Está el error budget quemándose más rápido que baseline?
Si ninguna de esas preguntas está instrumentada, el cronograma de rollout es una línea de tiempo, no un loop de validación.
Una configuración que se sostiene en producción: define dos ventanas de evaluación SLO. Una corta (15 minutos) atrapa fallos rápidos:una query mala de base de datos, un mismatch de schema, una regresión en una ruta crítica. Una más larga (24 horas o un ciclo de tráfico completo) atrapa degradación gradual:memory leaks, cache pressure, edge cases en segmentos de tráfico de baja frecuencia. Requiere que ambas ventanas muestren green antes de cualquier avance. Si cualquiera se viola, detén el rollout y pagina el on-call.
El porcentaje es un dial. La ventana SLO es el gate. Ambos son requeridos.
Kill Switch Engineering: Diseñalo Antes de Necesitarlo
El kill switch no es un fallback. Es una decisión de design de primera clase que debe existir antes de la primera línea de código de feature.
Un kill switch diseñado bajo presión es un kill switch con supuestos no examinados. Lo estás testeando por primera vez durante un incidente activo, dentro de una sesión terminal abierta desde una notificación de PagerDuty, con cinco personas mirando un thread de Slack. Ese es el peor momento posible para descubrir que tu ops flag targeting usuarios por session ID y tu servicio de sesión está actualmente degradado.

Tres propiedades que son inegociables para cualquier kill switch destinado a uso en producción:
Evaluación local sub-50ms: la verificación de flag no puede ser una llamada de red a un servicio de evaluación remoto. Si la evaluación depende de un servicio que podría estar degradado, tienes una dependencia circular en tu ruta de respuesta a incidentes.
Valor de fallback explícito: ¿qué retorna el flag cuando el servicio de flags es inaccesible? Esto debe estar documentado, definido en código, y testeado. "Lo que sea que el SDK default sea" no es una respuesta.
Testeado bajo falla de dependencias: los kill switches deben ser parte de tu rotación de chaos engineering. Valídalos contra escenarios donde auth está degradado, donde el servicio de flags en sí está down, y donde la latencia de red al endpoint de evaluación excede 2 segundos.
Los equipos que ejecutan incident response limpiamente son los que ensayaron. El kill switch es parte del runbook. Hazlo aburrido.
Flag Debt: La Deuda Técnica Que Nadie Pone en la Roadmap
Equipos que adoptan feature flags agresivamente a menudo acumulan lo que a veces se llama flag debt: flags que completaron su propósito pero nunca fueron removidos. La característica se lanzó, el experimento concluyó, la beta terminó. El flag se quedó.
En 50 flags, esto es una molestia menor. En 500 flags en un sistema distribuido, es un riesgo operacional activo. Cada flag es una rama de código que requiere mantenimiento, testing, y comprensión durante investigación de incidentes. Un desarrollador intentando entender una falla a las 2am no quiere trazar 40 ramas condicionales para encontrar la relevante.
Un patrón observado en múltiples equipos de plataforma: evaluación de flag middleware apareciendo en los cinco primeros stack frames para p99 latency. La causa en la mayoría de casos es flags stale con reglas de targeting complejas que evalúan docenas de condiciones por request, cargando el peso de decisiones tomadas hace dos años que nadie se sintió cómodo deletear.
La contramedida es organizacional más que técnica. Cada flag creado debe tener tres atributos: un propietario, un tipo (release, experiment, ops, permission), y una fecha de remoción esperada. Los release flags deben removerse dentro de dos sprints del rollout completo. Los experiment flags deben removerse cuando el experimento concluye, no "cuando alguien tenga tiempo". El inventario de flags debe ser auditable on-demand y surfaceado en dashboards de health de ingeniería.
Granularidad de Targeting: La Dimensión Que Se Quiebra a Escala Enterprise
La mayoría de plataformas de feature flags soportan rollouts basados en porcentaje y targeting básico de atributos de usuario. El gap que emerge a escala enterprise es granularidad de targeting: la habilidad de expresar reglas de rollout que son específicas suficientemente para ser útiles sin ser complejas suficientemente para ser unmaintainable.
Una jerarquía de targeting útil para rollouts en producción a nivel de equipo de plataforma:
Environment-level: producción, staging, preview. El primer gate, no el único.
Infrastructure segment: data center, availability zone, o Kubernetes cluster. Útil para aislar blast radius geográfico.
Account o tenant: para plataformas B2B SaaS, rollout por-account es a menudo más seguro que por-user-percentage, porque puedes observar el patrón de tráfico completo de una account en lugar de una muestra estadística.
User cohort: usuarios beta, usuarios internos, power users por tier de actividad.
Session attribute: útil para experiment flags, peligroso para ops flags.
Las plataformas que implementan esto bien (LaunchDarkly y Statsig son las más citadas por equipos SRE haciendo esto a escala) permiten composición de reglas complejas sin requerir tiempo de ingeniería para modificar la lógica de targeting durante un rollout activo. Esa capacidad self-service es la diferencia entre una pausa de 30 segundos y un ticket al equipo de plataforma.
Las plataformas que implementan esto mal te fuerzan a elegir entre granularidad de targeting y simplicidad operacional. Ese tradeoff emergirá a las 3am.
Lo Que el Post-Mortem Sigue Encontrando
Todo post-mortem para un incidente en producción relacionado a feature hace el mismo conjunto de preguntas. ¿Estaba la feature detrás de un flag? ¿Era el rollout progresivo? ¿Había una condición de validación entre etapas? ¿Fue el kill switch testeado antes del incidente?
Si todas cuatro respuestas son sí, el incidente es un problema de calibración: thresholds demasiado sueltos, reglas de targeting con un edge case, comportamiento de evaluación de SDK bajo network partition que no fue contabilizado. Estos son solucionables con cambios de configuración y actualizaciones de runbook.
Si cualquier respuesta es no, el incidente es un problema de arquitectura. Los feature flags no son una conveniencia de debugging. Son una decisión de arquitectura de despliegue. Esa decisión o existe antes de que la feature se lance, o no existe en absoluto.
La pregunta vale la pena responder antes del próximo release: ¿qué diría el post-mortem sobre este rollout si algo sale mal esta noche?