Feature Flags

Aprende qué son los Feature Flags, qué problemas resuelven, cómo implementarlos en .NET y cuáles son sus casos de uso más comunes.

Es común que una funcionalidad tarde varios días o incluso semanas en estar lista. Sin embargo, eso no significa que el resto del equipo pueda dejar de desplegar correcciones o nuevas características mientras tanto.

¿Cómo hacemos para integrar código incompleto sin exponerlo a los usuarios? ¿Qué pasa si queremos habilitar una funcionalidad solo para un grupo de clientes, realizar una prueba A/B o desactivarla rápidamente ante un problema en producción?

Los Feature Flags (también conocidos como Feature Toggles) son un patrón que permite controlar el comportamiento de una aplicación en tiempo de ejecución, habilitando o deshabilitando funcionalidades sin necesidad de realizar un nuevo despliegue.


#¿Qué es un Feature Flag?

Un Feature Flag es un mecanismo que permite decidir si una funcionalidad debe ejecutarse o no en tiempo de ejecución.

Aunque la implementación más simple consiste en una bandera booleana, un Feature Flag puede evaluarse utilizando distintos criterios, como el porcentaje de usuarios, el entorno, el rol del usuario, una ventana de tiempo o cualquier regla de negocio definida por la aplicación.

La idea principal es desacoplar el deployment del release. Es decir, el código puede desplegarse en producción sin que necesariamente esté disponible para los usuarios.


#¿Qué problema resuelven?

Sin Feature Flags, el despliegue y el lanzamiento de una funcionalidad suelen ocurrir al mismo tiempo.

Esto trae algunas limitaciones:

  • Una funcionalidad incompleta puede bloquear un despliegue.
  • Es común mantener ramas de larga duración para evitar que código sin terminar llegue a producción.
  • Si una funcionalidad falla, muchas veces es necesario realizar un rollback completo de la aplicación.

Con Feature Flags, el código puede desplegarse cuando el equipo lo considere conveniente, mientras que la decisión de habilitar la funcionalidad puede realizarse más adelante, incluso sin reiniciar la aplicación.

En otras palabras:

Deployment y Release dejan de ser el mismo evento.


#Implementación en .NET

Microsoft proporciona el paquete Microsoft.FeatureManagement.AspNetCore, que simplifica la implementación de Feature Flags en aplicaciones ASP.NET Core.

#Instalación

Agregar el paquete al proyecto.

BASH
dotnet add package Microsoft.FeatureManagement.AspNetCore

#Registrar el servicio

Registrar Feature Management durante la configuración de la aplicación.

CSHARP
builder.Services.AddFeatureManagement();

#Definir los Feature Flags

La forma más sencilla consiste en declararlos dentro de appsettings.json.

JSON
{
  "FeatureManagement": {
    "NewDashboard": false,
    "NewCheckout": true
  }
}

Para evitar errores por escribir nombres de flags manualmente, es recomendable centralizarlos en una clase.

CSHARP
public static class FeatureFlags
{
    public const string NewDashboard = nameof(NewDashboard);
    public const string NewCheckout = nameof(NewCheckout);
}

#Consultar un Feature Flag

La interfaz IFeatureManager permite consultar el estado de cualquier Feature Flag.

CSHARP
public class DashboardService
{
    private readonly IFeatureManager _featureManager;

    public DashboardService(IFeatureManager featureManager)
    {
        _featureManager = featureManager;
    }

    public async Task ShowDashboardAsync()
    {
        if (await _featureManager.IsEnabledAsync(FeatureFlags.NewDashboard))
        {
            Console.WriteLine("Nuevo Dashboard");
        }
        else
        {
            Console.WriteLine("Dashboard clásico");
        }
    }
}

La decisión se realiza en tiempo de ejecución, por lo que cambiar el estado del Feature Flag modifica el comportamiento de la aplicación sin necesidad de cambiar el código.


#Restringir un endpoint completo

Cuando una funcionalidad todavía no debería estar disponible, puede utilizarse el atributo FeatureGate.

CSHARP
[FeatureGate(FeatureFlags.NewDashboard)]
[ApiController]
[Route("dashboard")]
public class DashboardController : ControllerBase
{
}

Si el Feature Flag está deshabilitado, el endpoint dejará de estar disponible automáticamente.


#Filtros

No todos los Feature Flags son simplemente verdaderos o falsos.

La librería incluye distintos filtros que permiten controlar cuándo una funcionalidad debe habilitarse.

Algunos de los más utilizados son:

  • Boolean Filter: habilita o deshabilita la funcionalidad manualmente.
  • Time Window Filter: habilita una funcionalidad entre determinadas fechas.
  • Percentage Filter: habilita la funcionalidad para un porcentaje de usuarios.
  • Targeting Filter: habilita la funcionalidad para usuarios o grupos específicos.

También es posible implementar filtros personalizados para adaptarlos a cualquier regla de negocio.


#Casos de uso

#Deploy ≠ Release

Probablemente el caso de uso más importante.

Una funcionalidad puede permanecer oculta durante días o semanas mientras el resto del sistema continúa desplegándose normalmente.

Cuando llega el momento del lanzamiento, simplemente se habilita el Feature Flag.


#Kill Switch

Si una funcionalidad comienza a generar errores en producción, no siempre es necesario realizar un rollback.

En muchos casos alcanza con desactivar el Feature Flag.

Esto reduce considerablemente el tiempo de respuesta ante incidentes.


#Rollout gradual

No todas las funcionalidades deberían habilitarse para todos los usuarios al mismo tiempo.

Es posible comenzar habilitando la funcionalidad para un pequeño porcentaje de usuarios y aumentar gradualmente su disponibilidad mientras se monitorea el comportamiento del sistema.


#Beta privada

Algunas funcionalidades solo deberían estar disponibles para determinados clientes, usuarios internos o testers.

Los Feature Flags permiten controlar este acceso sin mantener versiones distintas de la aplicación.


#A/B Testing

Otra aplicación frecuente consiste en mostrar distintas implementaciones de una misma funcionalidad.

Por ejemplo:

  • 50% de los usuarios visualizan la versión actual.
  • 50% visualizan una nueva experiencia.

Luego pueden compararse métricas como conversión, tiempo de uso o interacción para determinar cuál ofrece mejores resultados.


#Buenas prácticas

#Los Feature Flags deberían ser temporales

Una vez que una funcionalidad se estabiliza y ya no existe la posibilidad de volver atrás, el Feature Flag debería eliminarse.

Mantener Feature Flags antiguos incrementa la complejidad del código y genera deuda técnica.


#Un Feature Flag debería controlar una única funcionalidad

Evitá reutilizar el mismo flag para controlar comportamientos diferentes.

Cada Feature Flag debería tener una única responsabilidad.


#Evitá anidar Feature Flags

Este tipo de código suele ser una señal de alarma.

CSHARP
if (await featureManager.IsEnabledAsync(FeatureFlags.FeatureA))
{
    if (await featureManager.IsEnabledAsync(FeatureFlags.FeatureB))
    {
        // ...
    }
}

La cantidad de combinaciones posibles crece rápidamente y dificulta las pruebas.


#Utilizá nombres descriptivos

Un nombre como:

TEXT
Feature1

dice muy poco.

En cambio:

TEXT
NewCheckout
EnableDiscountCoupons
ExperimentalSearch

resultan mucho más fáciles de entender.


#Eliminá los Feature Flags que ya no aportan valor

Los Feature Flags no deberían convertirse en configuración permanente.

Si una funcionalidad ya quedó estable y siempre permanecerá habilitada, eliminar el Feature Flag simplifica el código y reduce el mantenimiento futuro.

#architecture #feature-flags #dotnet