← maurobernal.com.ar

Etiqueta: Azure App Configuration

  • Feature Management en .NET (Parte 2): Filtros Dinámicos, Hot Reload y Feature Flags vs. Versionado

    En el post anterior vimos los conceptos base de Feature Flags con Microsoft.FeatureManagement. Acá vamos a profundizar en tres capacidades que marcan la diferencia entre usar flags como simples condicionales y usarlos como una herramienta real de arquitectura: filtros dinámicos con Minimal APIs, recarga en caliente como Kill Switch, y la diferencia conceptual con el versionado de APIs. También incluyo la comparativa completa entre ambos enfoques, que es algo que me preguntan frecuentemente.

    Feature Flags Estáticas en Minimal APIs

    El caso más directo: un interruptor booleano evaluado en tiempo de ejecución. Lo interesante con Minimal APIs es que la integración es aún más limpia que en controllers tradicionales — IFeatureManager se inyecta directamente en el handler del endpoint.

    // appsettings.json
    {
      "FeatureManagement": {
        "NewCheckout": false
      }
    }
    
    // Program.cs
    var builder = WebApplication.CreateBuilder(args);
    builder.Services.AddFeatureManagement();
    var app = builder.Build();
    
    app.MapGet("/checkout", async (IFeatureManager fm) => 
    {
        if (await fm.IsEnabledAsync("NewCheckout"))
        {
            return Results.Ok("Procesando con el NUEVO flujo de pago.");
        }
        
        return Results.Ok("Procesando con el flujo de pago CLÁSICO.");
    });
    
    app.Run();

    La evaluación ocurre en cada petición. Cambiar false por true en el archivo de configuración actualiza el comportamiento sin reiniciar el proceso.

    Filtros Dinámicos: Canary Releases y Pruebas A/B

    Los flags booleanos globales resuelven muchos casos, pero en producción real necesitás más granularidad. Los Feature Filters permiten activar características basándose en reglas contextuales evaluadas en cada petición. .NET incluye dos filtros nativos listos para usar:

    • PercentageFilter: activa el flag para un porcentaje del tráfico. Ideal para Canary releases.
    • TimeWindowFilter: activa el flag solo durante una ventana temporal. Ideal para lanzamientos programados o mantenimientos.

    Ejemplo con PercentageFilter + FeatureGate en un controller:

    // appsettings.json — 50% del tráfico ve el motor Beta
    {
      "FeatureManagement": {
        "BetaSearch": {
          "EnabledFor": [
            {
              "Name": "Percentage",
              "Parameters": { "Value": 50 }
            }
          ]
        }
      }
    }
    
    // Program.cs — registrar el filtro
    builder.Services.AddFeatureManagement()
        .AddFeatureFilter<PercentageFilter>();
    
    // SearchController.cs
    [ApiController]
    [Route("api/[controller]")]
    public class SearchController : ControllerBase
    {
        [HttpGet]
        [FeatureGate("BetaSearch")] // 404 automático para el 50% que no aplica
        public IActionResult Get()
        {
            return Ok("Resultados del motor de búsqueda Beta.");
        }
    }

    Lo que me gusta de este enfoque es que el [FeatureGate] hace que el endpoint directamente no exista para quien no aplica al filtro. No hay lógica de «si no entra acá, redirigí allá» — el framework lo maneja solo.

    Hot Reload y Kill Switches: El Poder Real de los Feature Flags

    Esta es la capacidad que más valoro en producción. El sistema de Feature Management se integra con IOptionsSnapshot, el mecanismo reactivo de configuración de .NET. Cuando modificás la fuente de configuración — ya sea el appsettings.json, una variable de entorno o Azure App Configuration — el estado del flag se actualiza en memoria automáticamente en la siguiente petición. Sin reinicio, sin downtime.

    El caso de uso más crítico: el Kill Switch. Si una feature nueva empieza a generar errores en producción, en lugar de hacer rollback del deploy entero (proceso que puede tomar minutos), simplemente cambiás el flag a false y la próxima petición ya usa el código anterior.

    var builder = WebApplication.CreateBuilder(args);
    builder.Services.AddFeatureManagement();
    var app = builder.Build();
    
    app.MapGet("/health", async (IFeatureManager fm) => 
    {
        // Un operador cambia "MaintenanceMode" a true en appsettings.json.
        // La SIGUIENTE petición refleja el cambio al instante, sin reiniciar el proceso.
        bool isMaintenance = await fm.IsEnabledAsync("MaintenanceMode");
        
        if (isMaintenance)
        {
            return Results.StatusCode(503); // Service Unavailable
        }
        
        return Results.Ok("Sistema Operativo");
    });
    
    app.Run();

    En proyectos donde integramos con Azure App Configuration, esto va un paso más allá: podés cambiar el flag desde un panel web, sin acceso al servidor, y el efecto es inmediato. Para equipos de guardia nocturna o sistemas de alta disponibilidad, esto es invaluable.

    Feature Flags vs. Versionado de API: La Confusión Más Frecuente

    Es la pregunta que más aparece cuando presento este tema. Son herramientas distintas para problemas distintos, aunque superficialmente parecen hacer lo mismo (exponer diferentes comportamientos según contexto).

    CriterioFeature FlagsVersionado de API
    Problema que resuelveExposición controlada: gestiona quién y cuándo accede a un cambioCompatibilidad de contratos: clientes antiguos no se rompen ante cambios destructivos
    Tiempo de vidaEfímero. Una vez estable, la flag y el código viejo deben eliminarse (deuda técnica)Prolongado. v1 y v2 coexisten por años
    Mecanismo de controlConfiguración externa, reglas de negocio, evaluación en runtimeRutas estáticas (/api/v1/), headers HTTP o referencias de ensamblado
    InfraestructuraUn solo binario con todos los caminos lógicosPueden ser múltiples binarios o deploys paralelos

    La regla que uso: si el cambio es interno y temporal (lo vas a limpiar cuando sea estable), usá Feature Flags. Si el cambio rompe el contrato público con consumidores externos que necesitan tiempo para migrar, usá versionado. En proyectos complejos, ambos conviven sin problema.

    Próximos pasos

    Estos tres patrones cubren la gran mayoría de los casos de uso cotidianos. El siguiente nivel son los Custom Feature Filters — filtros personalizados que habilitan flags según el tenant de la base de datos, el rol del usuario, la región geográfica o cualquier lógica de negocio propia. Y después de eso, la integración con Azure App Configuration para centralizar todos los flags en un servicio externo con targeting por usuario o segmento.

    ¿Te interesa alguno de esos dos temas para el próximo artículo? Dejalo en los comentarios.

Tags

tsql (27)mssql (26)devops (21)sql (20)dotnet (18)docker (16)performance (14)contenedores (11)dotnet10 (10)linux (9)csharp (8)microservicios (8)angular (8)angular21 (7)sql server (6)issabel (6)kubernetes (6)docker-compose (6)typescript (6)aot (6)