Qué es un feature flag: Guía completa de implementación
Resumen
Los feature flags son sentencias condicionales que controlan el comportamiento en tiempo de ejecución sin necesidad de redeploy. Los equipos los usan para desplegar gradualmente, mergear trabajo sin terminar y degradar features rápidamente. Pero con 200 flags, la deuda técnica crece: requieren un proceso sano de limpieza, nombrado, asignado y con fecha de expiración.
Un feature flag es una condición en tu código que decide en tiempo de ejecución si un comportamiento está activado o desactivado, sin necesidad de un nuevo deploy. Esa es la idea completa. ¿Qué es un feature flag en la práctica? Una sentencia if cuya respuesta viene de configuración, una fila de base de datos, o un servicio de flags en lugar de estar hardcodeada.
El concepto es simple. Vivir con 200 de ellos en un repositorio no lo es, y esa segunda parte es realmente de qué trata esta guía.
¿Qué aspecto tiene un feature flag en el código?
Aquí está la versión más pequeña y útil:
if (flags.isEnabled("new-checkout", { userId })) {
return renderNewCheckout();
}
return renderOldCheckout();Ambos paths de código se envían en el mismo build. El valor del flag vive en un lugar que puedes cambiar sin redeploy: una variable de entorno, un archivo JSON, una tabla, o un servicio alojado. Cambia el valor, y el comportamiento cambia en la siguiente evaluación.
Esa separación es el punto. El deploy es poner código en servidores. El release es permitir que los usuarios lo vean. Los flags dividen esos dos eventos, así que hacer merge a main ya no significa "todos obtienen esto ahora".

¿Por qué los equipos usan feature flags?
Tres razones surgen una y otra vez en equipos reales de 5 a 50 ingenieros.
Fusionar trabajo sin terminar de forma segura. Haces commit de la feature a medio construir detrás de un flag que está apagado, y tu rama nunca vive por tres semanas. Esto es lo que hace que el trunk-based development sea viable.
Desplegar gradualmente. Enciende un cambio para usuarios internos, luego 5% del tráfico, luego todos. Si las tasas de error suben, lo apagas en segundos.
Eliminar algo rápido. Cuando un proveedor de pagos falla a las 2 a.m., un flag permite que el on-call degrade una feature en lugar de hacer rollback de un release completo.
Ninguno de estos requiere un vendedor. Un flag puede ser un booleano en una tabla de configuración. Salta la plataforma hasta que necesites rollouts porcentuales, audit trails, o no-ingenieros toggling things.
¿Cuáles son los cuatro tipos de feature flags?
El artículo ampliamente citado de Pete Hodgson sobre feature toggles en el sitio de Martin Fowler clasifica flags por cuánto tiempo viven y qué tan frecuentemente cambia la decisión. Las categorías siguen siendo el modelo mental más claro.
Release: vive días a semanas, volteado por ingenieros. Ejemplo: ocultar un redesign de checkout sin terminar.
Experiment: vive semanas, volteado por product y data. Ejemplo: un test A/B de dos páginas de precios.
Ops: vive horas a siempre, volteado por on-call. Ejemplo: un kill switch para un servicio de recomendaciones lento.
Permission: vive meses a años, volteado por product y support. Ejemplo: acceso beta o features solo para premium.
La columna de duración importa más. Un release flag que sobrevive su release es un bug que no has encontrado aún. Un permission flag que se elimina en un sprint de limpieza es un outage que no has tenido aún.
Nombra y etiqueta el tipo cuando creas el flag. Seis meses después, nadie recuerda en qué categoría estaba "new-nav-v2".

¿Cómo despliegas un flag sin afectar a usuarios?
La secuencia aburrida funciona mejor.
Envía el código con el flag apagado. Verifica que nada cambió.
Habilítalo para tu propio equipo en producción. Úsalo por un día.
Habilítalo para 1% a 5% de usuarios, sticky por user ID así nadie cambia entre variantes mid-session.
Observa error rate, latency, y una métrica de negocio. Decide el threshold antes de empezar, no mientras miras un dashboard.
Aumenta a 100%, espera un período definido, luego elimina el flag.
El paso cinco es el que los equipos saltan. Vamos a ver por qué eso cuesta más de lo que piensas.
Una nota práctica sobre evaluación: mantén las lecturas de flags baratas y fail-safe. Si el servicio de flags está caído, tu código necesita un default. Elige el default por flag, a propósito. Un kill switch debe fallar a "safe", mientras que una feature nueva debe fallar a "off".
¿Por qué los feature flags se convierten en deuda técnica?
Cada flag es una rama en tu código. Dos flags crean cuatro caminos posibles, diez flags crean 1.024, y casi seguramente testeaste un puñado de ellos. La guía de GrowthBook sobre deuda de flags cita investigación mostrando que aproximadamente 75% de los toggle components seguían en codebases hasta 49 semanas después de ser introducidos, aunque la mayoría de desarrolladores dijo que planeaban eliminarlos.
Hodgson lo pone bien en el mismo artículo de Fowler: los equipos savvy tratan toggles como inventario con un costo de tenencia, y trabajan para mantener ese inventario bajo.
La historia de horror clásica es Knight Capital en 2012. Un flag de una feature retirada fue reutilizado para comportamiento nuevo mientras código antiguo seguía en un servidor. Ese desajuste contribuyó a aproximadamente $460 millones en pérdidas en menos de una hora. Tu flag stale probablemente no hará eso. Hará algo más quieto: un refactor que rompe una rama que nadie sabía que existía, o un new hire pasando una tarde averiguando cuál de dos checkout paths es el real.

¿Cómo encuentras cada flag en un codebase existente?
Esta es la pregunta que la documentación del vendedor salta, y es donde la mayoría de equipos se atascan. El dashboard del flag te dice qué está configurado. No te dice dónde se lee cada flag en código, o si el code path detrás de un flag "off" sigue siendo alcanzable.
Comienza con el enfoque barato:
# cada literal key de flag leído vía tu wrapper
rg -n 'isEnabled\("' src/ | sort
# flags definidos pero nunca referenciados
comm -23 <(jq -r 'keys[]' flags.json | sort) \
<(rg -o 'isEnabled\("([^"]+)"' -r '$1' src/ | sort -u)Esto se desmorona rápido. Las keys de flag construidas con string concatenation no aparecen en grep. Los flags pasados a través de funciones helper ocultan sus call sites. Los monorepos y setups multi-repo multiplican el problema, porque la misma key puede ser leída por tres servicios.
Eso es donde leer código con tooling ayuda. Las herramientas de búsqueda de código que entienden tu repo pueden responder "¿dónde se evalúa new-checkout, y qué depende del resultado?" en una query en lugar de una tarde de grep. Cursor y GitHub Copilot manejan esto razonablemente dentro de un repo. Across varios repos, necesitas un índice que abarque todos ellos, que es el caso que construimos codebasechat para.
¿Qué aspecto tiene un proceso sano de limpieza de flags?
Trata la eliminación como parte del trabajo, no como una tarea para después.
Crea el ticket de eliminación con el flag. Enlázalo en la descripción del flag. Si el ticket no existe, el flag no se envía.
Asigna un owner y una fecha de expiración en cada flag no permanente. Alrededor de 90 días sin cambios es un trigger razonable para review.
Elimina en dos pull requests. Primero elimina el check del flag y mantén el winning path. Luego elimina la rama muerta y sus tests. Los diffs pequeños son diffs revisables.
Añade un test time bomb. Un test que falla cuando un release flag pasa su fecha de expiración convierte una buena intención en un red build.
Establece un límite. Si tienes 40 flags activos y el límite es 40, añadir uno significa eliminar uno.
El análisis estático ayuda aquí también. Una herramienta como CodeScene puede mostrar qué archivos tienen la lógica condicional más enredada, que es usualmente donde los flags antiguos se agrupan. SonarQube señala código inalcanzable y muerto después de que eliminas un check.
¿Cómo testeas código que está detrás de un flag?
Testing es la parte que nadie presupuesta. Con dos paths por flag, tu test suite necesita cubrir ambos, al menos para los flags que guardan comportamiento riesgoso.
Mantenlo práctico. Testea los estados on y off de cada release flag en unit tests, inyectando el valor del flag en lugar de leer un servicio live. Ejecuta una suite end-to-end contra la configuración de producción default, porque eso es lo que los usuarios obtienen hoy. Luego ejecuta un segundo pass con el flag activado para la feature que estás a punto de lanzar.
No intentes testear cada combinación. Con diez flags no puedes. En su lugar, mantén flags independientes: un flag que cambia comportamiento solo cuando otro flag también está activado es un design smell, y es lo primero que hay que desenredar.
¿Qué error cometen los ingenieros nuevos con flags?
Los juniors tienden a hacer los mismos tres errores, y cada uno es barato de prevenir en review.
Anidar flags. Un flag dentro de otro crea un path que solo existe cuando ambos están activados. Pide un flag único con un nombre claro en su lugar.
Poner lógica en el nombre del flag. Una key como "show-new-nav-to-premium-users-in-eu" codifica una regla de targeting que pertenece al servicio de flags, no en un string.
Olvidar el default. Si la búsqueda de flag falla, ¿qué pasa? Haz que el autor escriba la respuesta en la descripción del pull request.
Las primeras dos semanas de un new hire son exactamente cuando se topan con flags antiguos sin owner. Un registro de flags corto, con un tipo, un owner, y una fecha de eliminación para cada entrada, ahorra varias horas de preguntar por ahí.
¿Cuándo debes saltar feature flags?
Los flags no son gratis, así que sáltalos cuando:
El cambio es pequeño, reversible, y un deploy lejos de un rollback. Un flag añade un code path sin ganancia.
El cambio toca un schema de base de datos de una forma que un flag no puede ocultar. Usa expand-and-contract migrations en su lugar.
Tu equipo no tiene proceso para eliminar flags. Arregla eso primero, o estás pidiendo prestado contra la readability futura.
Y úsalos sin dudar cuando un cambio es riesgoso, user-facing, y difícil de revertir mediante redeploy. Los flujos de pago, cambios de auth, y cualquier cosa con una data migration detrás califican.
Qué haríamos realmente en un equipo de diez
Comienza con un booleano en config y una función wrapper, así cada lectura de flag pasa por un lugar. Ese único choke point hace la lista de flags greppable, auditable, y fácil de migrar a un servicio alojado después.
Etiqueta cada flag por tipo, dale un owner, y presenta el ticket de eliminación en el día uno. Revisa la lista mensualmente por diez minutos. Elimina los flags que han estado en 100% por dos semanas.
Un feature flag es un préstamo. Tómalo cuando te ahorre un release riesgoso, y devuélvelo antes de que el interés se muestre en tu próximo refactor.