Feature flags en produccion: gestion de riesgo sin frenar desarrollo
El problema que los feature flags resuelven
Hay una tension fundamental en el desarrollo de software: el equipo quiere desplegar codigo frecuentemente (idealmente, varias veces al dia), pero el negocio quiere controlar cuando y a quien se expone una funcionalidad nueva. Sin feature flags, estas dos necesidades son incompatibles. O despliegas y todo el mundo ve la funcionalidad nueva, o mantienes una rama de larga duracion que diverge del main y genera conflictos de merge que nadie quiere resolver un viernes a las cinco.
Los feature flags desacoplan el despliegue del codigo de la activacion de la funcionalidad. Es una practica fundamental del desarrollo a medida moderno. Puedes mergear codigo a main, desplegarlo a produccion, y mantenerlo invisible hasta que decidas activarlo. Esto parece simple, y a nivel conceptual lo es. En la practica, la mayoria de las implementaciones de feature flags acaban siendo una fuente de complejidad, deuda tecnica y bugs sutiles.
Llevamos usando feature flags en todos nuestros proyectos de produccion desde hace tres anos. Estas son las lecciones.
Taxonomia de flags
No todos los feature flags sirven para lo mismo, y tratarlos de forma homogenea es el primer error. Distinguimos cuatro tipos:
Release flags. Controlan la visibilidad de una funcionalidad nueva. Tienen una vida util corta: se crean cuando la funcionalidad empieza a desplegarse y se eliminan cuando la funcionalidad esta disponible para todos los usuarios. Vida tipica: 2-6 semanas.
Experiment flags. Sirven para A/B testing. Dividen el trafico entre variantes y recopilan datos para tomar una decision. Vida tipica: 2-8 semanas. Requieren integracion con el sistema de analytics.
Ops flags. Interruptores operativos que permiten desactivar funcionalidades o degradar servicios en caso de incidente. El clasico: un kill switch para una integracion con un servicio externo que se cae. Vida tipica: indefinida, pero deben revisarse periodicamente.
Permission flags. Controlan acceso a funcionalidades por segmento de usuarios (plan de pago, rol, geografia). Son los que mas se parecen a configuracion de negocio y los que tienen la vida util mas larga.
Cada tipo tiene requisitos diferentes de evaluacion, almacenamiento y lifecycle. Tratar un experiment flag con la misma infraestructura que un ops flag es como usar la misma herramienta para atornillar y para martillar. Funciona, pero mal.
Patrones de implementacion
El if/else ingenuo
La implementacion mas basica es un condicional:
if feature_flags.is_enabled("new_checkout"):
return render_new_checkout(request)
else:
return render_old_checkout(request)
Funciona para un flag. Para cincuenta, el codigo se vuelve ilegible, intesteable y fragil. Cada flag anade una bifurcacion que multiplica los caminos de ejecucion. Diez flags binarios crean 1.024 combinaciones posibles. No vas a testear las mil veinticuatro.
Strategy pattern
Una implementacion mas limpia usa el patron strategy:
class CheckoutStrategy:
def render(self, request): ...
class NewCheckout(CheckoutStrategy): ...
class OldCheckout(CheckoutStrategy): ...
strategy = flag_router.get_strategy("checkout", request.user)
return strategy.render(request)
El flag determina que estrategia se inyecta, y el codigo de negocio no sabe que hay un flag. Esto hace que las funcionalidades sean testables de forma independiente y que eliminar el flag sea trivial: borras la estrategia antigua y haces que la nueva sea el default.
Trunk-based development con flags
El workflow que mejor funciona con feature flags es trunk-based development: todo el mundo trabaja en main (o en ramas muy cortas que se mergean a main diariamente), y las funcionalidades incompletas se ocultan detras de flags.
Las reglas practicas:
- Nunca despliegues un flag activado por defecto. Si la funcionalidad no esta lista, el flag esta off.
- El flag se crea antes de escribir la primera linea de codigo. No retrofittear flags en codigo existente.
- Cada flag tiene un owner y una fecha de expiracion. Si no tiene owner, nadie lo eliminara.
- El flag se prueba en ambas posiciones. Tu CI debe ejecutar tests con el flag on y con el flag off.
Despliegue progresivo
Los feature flags habilitan estrategias de despliegue progresivo que reducen drasticamente el riesgo:
Canary release. Activas la funcionalidad para el 1% del trafico. Monitorizas error rate, latencia, metricas de negocio. Si todo esta bien, subes a 5%, luego 25%, luego 100%. Si algo falla en el 1%, revertir es desactivar el flag. Tiempo de reversion: segundos, no los 15-30 minutos de un rollback de despliegue.
Targeted rollout. Activas la funcionalidad para un segmento especifico: usuarios internos, beta testers, clientes de un plan concreto, usuarios en una geografia. Esto permite validar en produccion con usuarios reales antes del lanzamiento general.
Scheduled activation. Marketing quiere lanzar la funcionalidad el martes a las 10:00. Con un flag programado, el equipo de ingenieria despliega el codigo el viernes (cuando tiene tiempo para verificar), y el flag se activa automaticamente el martes. Zero-stress launch.
Hemos usado canary releases en un sistema de procesamiento de envios que gestionaba 3.000 operaciones diarias. La nueva logica de calculo de rutas se desplego activandola primero solo para envios nacionales (que representaban el 60% del volumen pero eran mas simples). Dos semanas despues, activamos para internacionales. Los tres bugs que detectamos en la primera fase nunca llegaron a afectar al trafico internacional.
La deuda de flags obsoletos
Y aqui esta el problema que nadie quiere afrontar. Cada feature flag que no se elimina despues de cumplir su funcion es deuda tecnica. No deuda teorica. Deuda real que causa bugs.
Un caso que vivimos en 2024: un flag de release que llevaba 9 meses activo para el 100% del trafico. Nadie lo habia eliminado. Un desarrollador nuevo cambio la logica del modulo sin darse cuenta de que habia un camino de ejecucion alternativo (el flag off) que seguia en el codigo. Seis meses despues, alguien desactivo el flag accidentalmente durante un cambio de configuracion. El sistema revirtio a una logica de 15 meses atras. Tardamos 3 horas en diagnosticarlo.
Politicas de lifecycle
La unica defensa contra la deuda de flags es una politica de lifecycle estricta:
TTL obligatorio. Cada flag tiene una fecha de expiracion. Para release flags, 30 dias despues de activacion al 100%. Para experiment flags, 14 dias despues de la decision. El sistema de flags debe alertar (o directamente fallar) cuando un flag supera su TTL.
Conteo y limite. Monitorizamos el numero total de flags activos. Nuestro limite interno es 25 flags concurrentes. Cuando nos acercamos, hay que limpiar antes de crear nuevos. Suena arbitrario, pero sin un limite explicito, el numero crece indefinidamente.
Flag removal como tarea de engineering. No es tech debt backlog. Es parte de la definicion de done del feature: el flag se elimina en el sprint siguiente al rollout completo. Si el flag no se elimina, el feature no esta terminado.
Dead code detection. Herramientas como Piranha (de Uber, open source) analizan el codigo y detectan flags que estan siempre en la misma posicion. Si un flag lleva 60 dias evaluandose como true, el condicional puede eliminarse y el codigo simplificarse automaticamente.
Herramientas: LaunchDarkly y alternativas
LaunchDarkly es el lider del mercado y tiene una razon para serlo: evaluacion en el edge con latencia de microsegundos, targeting complejo, integracion con todo, audit trail completo. Para equipos grandes con cientos de flags y necesidades de compliance, es la referencia.
El problema es el precio. LaunchDarkly cuesta a partir de 10 USD por seat/mes en el plan Pro, pero el coste real para un equipo de 20 personas con uso intensivo puede superar los 1.000 USD/mes. Para startups y pymes, esto no siempre encaja.
Alternativas que hemos evaluado:
Unleash. Open source, self-hosted. Evaluacion del lado del servidor con SDKs para los lenguajes principales. UI funcional para gestionar flags. La opcion pragmatica si ya tienes infraestructura propia y no necesitas evaluacion en el edge. Coste: hosting de un contenedor.
Flipt. Open source, escrito en Go. Extremadamente ligero. Evaluacion server-side. Sin dependencias externas. Ideal para equipos que quieren flags simples sin operacion compleja. Carece de targeting avanzado.
GrowthBook. Open source con plan hosted. Orientado a A/B testing con feature flags. Buena integracion con warehouses de datos para analisis de experimentos. La mejor opcion si tu caso de uso principal son experiments.
OpenFeature. No es una herramienta sino un estandar (CNCF). Define una API comun para feature flags que permite cambiar de provider sin modificar el codigo de la aplicacion. Piensa en OpenTelemetry pero para flags. Si no quieres vendor lock-in, implementar contra la API de OpenFeature y conectar el provider que elijas es la estrategia mas futura-proof.
Para nuestros proyectos, usamos Unleash en produccion con la API de OpenFeature en el codigo de aplicacion. Esto nos da la flexibilidad de cambiar a cualquier otro provider (incluyendo LaunchDarkly) si las necesidades crecen, sin tocar la logica de la aplicacion.
Antipatrones
Tres antipatrones que hemos visto repetidamente:
Flags como configuracion de negocio permanente. Un flag creado para “activar el modulo premium para el cliente X” que se queda para siempre porque es comodo. Esto no es un feature flag; es configuracion de la aplicacion. Debe vivir en un sistema de configuracion, no en el sistema de flags.
Flags anidados. Un flag que solo tiene efecto si otro flag esta activado. Las dependencias entre flags crean una complejidad combinatorial que es imposible de testear y dificil de razonar. Regla: si un flag depende de otro, uno de los dos sobra.
Evaluacion de flags en hot paths. Evaluar un flag en cada iteracion de un bucle que procesa 100.000 registros. La evaluacion de un flag deberia hacerse una vez por request o por operacion, no una vez por registro. Cache la decision al inicio del proceso.
Feature flags como cultura de ingenieria
Los feature flags no son una herramienta. Son una practica de ingenieria que refleja una cultura de despliegue seguro y experimentacion controlada. Usarlos bien requiere disciplina: crear con intencion, revisar con frecuencia, eliminar con urgencia.
La tentacion de dejar flags “por si acaso” es real. Resiste esa tentacion. Cada flag activo es un condicional en tu codigo que alguien tendra que entender, testear y mantener. El numero de flags no deberia crecer con el tiempo; deberia mantenerse estable, con flags nuevos reemplazando a flags retirados en un flujo continuo.
Un sistema de flags bien gestionado es invisible: nadie piensa en el porque simplemente funciona. Un sistema de flags mal gestionado es una mina de bugs impredecibles, combinaciones no testeadas y logica que nadie entiende. La diferencia esta en el lifecycle management, no en la herramienta. Si quieres profundizar en estrategias de despliegue y cloud, complementa este articulo con nuestro enfoque de DevOps.
Etiquetas
Sobre el autor
abemon engineering
Equipo de ingenieria
Equipo multidisciplinar de ingenieria, datos e IA con sede en Canarias. Construimos, desplegamos y operamos soluciones de software a medida para empresas de cualquier escala.
