Las feature flag también conocidas como feature toggles son una técnica que permite cambiar el comportamiento del sistema sin cambiar el código. Básicamente estos «interruptores/semáforos» nos permiten habilitar una funcionalidad en tiempo de ejecución sin tener que volver a desplegar el código. Es un concepto muy simple, tan simple como un if pero con unas consecuencias increíblemente poderosas. Por ejemplo, puede que la funcionalidad no este lista para una carga de peticiones alta, o puede hayamos tocado una parte del proyecto muy legacy y queramos ver los efectos solo a pequeña escala.
Según Accelerate, los equipos de alto rendimiento despliegan con más frecuencia y su tasa de fallos es menor. Parte de esto es posible porque utilizan herramientas, sistemas y procesos adecuados para su contexto. Con las feature toggles estamos separando el despliegue de una nueva funcionalidad con el uso de la misma, es decir, al usar feature toggles podemos desplegar siempre y la funcionalidad será utilizada en producción solo cuando nosotras la activemos. Esto puede cambiar drásticamente la forma en que operamos como equipos de desarrollo.
Aunque también es cierto que las features toggles introducen una complejidad inherente y lidiar con esta complejidad hace que tengamos que tener en cuenta una serie de factores de que trataremos más adelante.
Leer más: Cómo cambio mi vida desde que uso feature flagsVeamos un ejemplo
El código sería algo como esto:
public function validateBooking(BookingData $bookingData): bool
{
if($this->featureToggle->isEnabled('USE_NEW_BOOKING_VALIDATOR')){
$this->bookingValidator->validate($bookingData);
}else{
$this->runOldLegacyValidator($bookingData);
}
}
Imaginemos que tenemos una clase que tiene mucha lógica legacy, complicada,…, como por ejemplo validar una serie de datos. Queremos añadir más validaciones pero el código es difícil de extender (legacy). Por lo que decidimos reescribir el validador para que sea más extensible. Como esto puede tardar un poco, lo que podemos hacer es crear una feature toggle para integrar el código del nuevo validador lo antes posible. Con esto evitamos posibles dolores de cabeza a la hora de mergear, además podemos abrir este nuevo validador cuando lo necesitemos para probar cuando hay poco tráfico o en algún entorno controlado (más adelante veremos algunos casos de uso).
Características de las feature toggles
A pesar de que estamos añadiendo una capa de complejidad extra a la hora de desarrollar, esta complejidad nos aporta una serie de propiedades que merece la pena destacar:
- Acortamos el ciclo de desarrollo: sin feature toggles tenemos que estar muy seguro de la implementación porque en el momento que subamos a producción la funcionalidad estará disponible. Con feature toggles podemos abrir la feature en entornos controlados (p.e. dentro de los usuarios que acceden a la web con la VPN) por lo que podemos tener feedback instantáneo.
- Simplificamos el control de versiones: no necesitamos hacer ramas largas con todo el desarrollo, con lo que nos evitamos «merges infernales» y podemos ir integrando nuestro código en producción cada día.
- Test en Producción: hay feature toggles se pueden habilitar solo para ciertos usuarios, no es necesario tener «staging», «preproducción» u otros entornos que nunca son 100% iguales que producción. Podemos probar en producción de manera controlada.
- Desacoplamos las decisiones de negocio de la parte técnica: hay veces que una funcionalidad está lista, pero es necesario esperar a un cierto momento para publicarla, con las feature toggles le damos la posibilidad a negocio de abrir la feature cuando sea necesario o solo para ciertos usuario para obtener feedback que les ayudará en la toma de decisiones.
- Facilita el rollback cuando algo va mal: todas cometemos errores al implementar una funcionalidad, un que no se ha tenido en cuenta, una excepción no controlada,… si una funcionalidad falla en el momento de activarla, es tan fácil como volver a desactivarla y ya está.
- Releases más afinadas: las feature flags nos permiten desplegar código solo en algunos entornos o bajo ciertas condiciones. Imagina. que nuestra aplicación está presente en una serie de países, pues podríamos decidir habilitar una funcionalidad solo en algunos países para comprobar el comportamiento de los usuarios y habilitar en el resto de países dependiendo del feedback obtenido. Este manera de desplegar podría asimilarse a «canary releases» ya que minimizamos el riesgo de introducir una funcionalidad desplegando el cambio solo a un subconjunto de usuarios.
Seguramente nos dejemos atrás muchas otras características para las que las feature toggles son útiles, así que te ánimo a que escribas un comentario para ir añadiéndolas.
Cómo cambia el desarrollo cuando utilizamos feature flags
Mayormente utilizamos las feature flags para nuevas funcionalidad, pero podría utilizarse para refactorizar partes del código o para hacer test A/B,… además como hemos comentado podemos activar funcinalidades para un subconjunto de usuarios lo que nos da un gran control sobre los despliegues, separando completamente la subida a producción (deploy) de la activación de la funcionalidad(release), por lo que el flujo de trabajo de como se desarrolla cuando tenemos feature flags cambia un poco.
- Definición de la «User Story»: en el momento que estamos refinando la tarea, podemos comentar cómo vamos a hacer implementar la feature toggle. Imaginemos que la funcionalidad es un nuevo botón en el frontend que realiza una acción, dependiendo del caso podríamos decidir poner la feature flag solo para mostrar o no el boton o podríamos decidir devolver un 403 como respuesta del endpoint si la feature está deshabilitada. Por lo que desde la definición de la tarea debemos tener en cuenta cómo vamos a implementar las feature toggles.
- Implementación en el código: normalmente la nueva funcionalidad está deshabilitada por defecto, para que así el despliegue sea sencillo.
- Test: cuando la funcionalidad esté casi completada, podemos habilitarla solo para usuarios internos, así podemos comprobar como se comporta esa funcionalidad para usuarios reales en producción. Imaginemos que quieres integrar una nueva pasarela de pagos, sería tan sencillo como habilitarla para ciertos usuarios y hacer una prueba para ver si de verdad todo está correcto.
- Canary/Beta: después de haberla probado con usuarios internos, podemos decidir abrir la funcionalidad para un subconjunto de usuarios. Imaginemos que la funcionalidad hace varias consultas a la base de datos, poder probar la performance con usuarios reales nos proporciona feedback suficiente para saber si es necesario hacer ajustes.
- Iterar: cada vez que vamos habilitando la funcionalidad para un grupo de usuarios distintos obtenemos respuestas, feedback que nos pueden ayudar a refinar mucho más la funcionalidad: consultas que van lentas, casos no contemplados en un principio,…
- Release: cuando ya estamos listos para abrir a todo el mundo podemos estar tranquilas porque la funcionalidad ya ha sido testeada varias veces en entornos reales, lo que nos proporciona un arnés de seguridad suficiente. En cualquier caso, si algo no funciona como es debido, siempre podemos volver atrás con un solo botón, deshabilitando la feature toggle.
- Limpieza: una vez que todo está listo y que la funcionalidad lleva un tiempo en producción, es hora de eliminar la feature toggle y el código antiguo si lo hubiese.
Al final, lo más importante reside en que el despliegue del código y la liberación de la funcionalidad para que la utilicen los usuarios deben estar separadas. La funcionalidad debe estar disponible o no atendiendo a requerimientos de negocio, no a «detalles» técnicos».
Tipos de feature flags
Podemos utilizar feature flags para multitud de casuísticas, dependiendo de lo que necesitemos. No es necesario tener un gran herramienta de feature flags, muchas veces con tener la mentalidad de integrar rápido puede ser suficiente. Ahora detallaremos algunos casos en los que es interesante el uso de feature flags.
Ejecutar experimentos
Dado que los feature flags nos permiten cambiar el comportamiento con un «grado de control», podemos utilizar esta herramienta para ejecutar experimentos y comparar versiones alternativas.
Imaginemos que tenemos un botón «call to action» de un color y queremos ver si cambiando el color/mensaje del botón la conversión es mayor o menor. Lo que podemos hacer es servir el botón original a un porcentaje del trafico y el botón modificado a otra parte del tráfico y medir la conversión
Esta situación es un test A/B y utilizando feature flags podemos implementar este tipo de tests. Herramientas cómo scientist pueden ayudarnos o incluso plataformas como Google analytics permiten hacer este tipo de tests
Desactivando funcionalidades
También podemos utilizar feature toggles para desactivar funcionalidades en momentos de alta demanda. Imaginemos que tenemos una sección de comentarios que no es muy rápida y justo estamos haciendo una campaña de televisión, podríamos optar por desactivar los cometarios mientras que dure dicha campaña
Aquí podremos justificar que lo ideal es que la sección de comentarios vaya rápida, invertir tiempo en refactorizarla o X, pero hay veces que tenemos que tomar decisiones algo más complicadas y tener herramientas como feature toggles nos brindan la oportunidad de tener otras opciones sobre la mesa a la hora de decidir.
Alternativas a las ramas
Imaginemos que tenemos una idea revolucionaria, creamos una rama y nos ponemos a programar, después de unos 45 minutos tenemos un prototipo funcional. El problema es que integrar este prototipo en la rama principal puede causar «efectos colaterales», así que nos llevamos unos días más ajustando, probando y analizando todos los casos. Al intentar mergear lo que tenemos es un «merge infernal», porque han cambiado varias cosas y ahora. no sabemos que hacer.
Seguramente esta situación nos resulte familiar, así que esperamos que a estas alturas tengamos claro que las ramas «largas» no son una buena idea. Tenemos que intentar reducir al mínimo los conflictos integrándonos varias veces al día, para ello la forma más sencilla es utilizar feature flags
public function showRecomendations(ProductData $productData): Recomendations
{
$useML = false;
if($useML){
$recomendations = $this->calculateRecomendations($productData);
}else{
$recomendations = $this->oldWay($productData);
}
return $recomendations;
}
Con este simple if con un valor «hardcodeado» en el código podemos integrar nuestro código en la rama principal varias veces al día y estar seguras de que vamos a reducir los conflictos.
Este patrón nos permite tener el punto de conmutación en un solo lugar. Es esencial para que no se vuelva un lío mantener el numero de if/else al mínimo para centralizar la decisión en un solo punto. Este manera de desarrollar se llama branch by abstraction.
Recomendaciones a la hora de utilizar feature flags
Normalmente cuando aprendemos una nueva técnica, creemos que podemos utilizarla en todas parte, pero nada más lejos de la realidad. Las feature flags son una herramienta poderosa, pero hay que utilizarlas con mesura para no caer en el «feature flag hell»

Esta es una foto de la charla «SCPNA 2022 – EXTREME PROGRAMMING EN ENTORNOS ALTAMENTE OPERATIVOS – Fernando Díaz» donde Fernando nos explicaba que las feature flags son geniales, pero que si tenemos muchas a la vez pues no podemos conocer el estado del proyecto y menos aún podemos hacer un triage correcto de un bug porque tenemos una «mochila» con una carga cognitiva tremenda.
Aparte de este «problema» con las feature flags hay una serie de recomendaciones que debemos tener en cuenta a la hora de usar las feature flags:
- Siempre limpiar el código después de la release final. Encontrarnos feature flags que llevan habilitadas meses es algo que no gusta, que hace el código difícil de leer y que por supuesto incrementa nuestra carga cognitiva. Así que la recomendación es eliminar el código que ya no está activo. Nosotros nos ponemos una reunión el google calendar para eliminar la feature flags 2 semanas después de activarla y tenemos una reunión mensual donde vemos que feature flags están activas y si hay que desactivarlas o hay que moverla a «ficheros de configuración» porque son características propias. de un país/cliente.
- Usarlas con mesura: utilizar feature flags para todo no es necesario, hay que saber cuando son útiles. y cuando no. Por eso, desde el refinamiento de la user story es bueno hablar de como vamos a realizar la release.
- Tener nombres descriptivos: Llamar a una feature flag «feature-2» no ayuda a la hora de saber que hace, tener una pequeña regla. de nomenclatura ayuda, por ejemplo <TEAM-PROJECT-FEATURE> algo así como «booking-payments-paypalIntegration» ayuda mucho. Además si utilizamos herramientas como Unleash, añadir contexto como el canal de slack del equipo o el ticket de Jira,…
- Adoptar continuos delivery: utilizando feature flags podemos hacer continuos delivery con menos riesgo, por ejemplo habilitando un cron para subir cada hora desde las 9:00 a las 16:00 sabiendo que todo lo que esté en la rama principal se va a desplegar, hace que utilicemos feature flags para desligar el deploy de la release.
- Tener una panel para ver el estado de las feature flags: conocer cuando se activó/desactivo, cuantas feature flags tenemos activas, en que países, a qué usuarios,…
- No reutilizar feature flags: Ser ordenadas a la hora de eliminar/crear feature flags es algo importantísimo, no reutilizar un feature flag para otro desarrollo porque puede causar confusión
Herramientas para tener feature flags en nuestro proyecto
Hay muchísimas herramientas para tener feature flags en nuestro proyecto, desde hacer algo custom (es la solución en la mayoría de los casos) hasta usar librerías o plataformas como:
- https://github.com/github/scientist
- https://pheatureflags.io/
- https://www.growthbook.io/
- https://configcat.com/
- https://www.getunleash.io/
- https://launchdarkly.com/
- https://groundcontrol.sh/
Seguro que nos faltan muchísimas más, pero dependerá de nuestro contexto escoger cual será la que mejor nos conviene.
Conclusiones
Utilizar feature flags aumenta muchísimo la complejidad del sistema, hace que tengamos que pensar desde el principio cómo integrar esta nueva herramienta, pero a la vez nos aporta una gran flexibilidad. Desligamos el despliegue del código de la release y hacemos que las releases no dependen de decisiones técnicas, tan solo de criterios de negocio. Con las feature flags conseguimos que integrar ramas sea algo sencillo, por lo que movernos un flujo de desarrollo como trunk based development sea algo sencillo. Es cierto que las feature flags no son una bala de plata y que hay que tener en cuenta la complejidad extra que añaden, el integrar un nuevo sistema y sobre todo el pensar desde muy pronto como esa nueva funcionalidad encajaría con las feature flags. Pero puede que todo ese extra compense en tu contexto
Enlaces
- https://martinfowler.com/articles/feature-toggles.html
- https://code.flickr.net/2009/12/02/flipping-out/
- https://featureflags.io/literature/
- https://launchdarkly.com/blog/what-are-feature-flags
- https://semaphoreci.com/blog/feature-flags
–








Comenta la entrada