En pocas palabras
Técnica que envuelve código nuevo en condiciones configurables para desplegarlo desactivado, activarlo por cohortes y retirarlo sin redeploy.
Qué problema resuelve
Lanzamientos acoplados a despliegues, imposibilidad de integrar trabajo incompleto y rollbacks lentos ante un fallo funcional.
Cuándo utilizarlo
Entrega continua, lanzamientos progresivos o experimentos. Ejemplo: activar un nuevo modelo de scoring solo para el 5 % de las solicitudes de un país.
De la idea a la práctica
Funcionamiento, ejemplos y decisiones para pasar al siguiente nivel.
Cuatro tipos con ciclos de vida distintos
| Tipo | Propósito | Duración | Dinamismo |
|---|---|---|---|
| Release | Ocultar trabajo incompleto en trunk | Días o semanas | Estático por entorno |
| Experiment | A/B testing con cohortes | Semanas | Por petición |
| Ops | Kill switch, degradar funciones costosas | Variable, a veces permanente | Rápido de cambiar |
| Permission | Funciones por plan, rol o país | Larga | Por usuario |
Mezclarlos en un mismo sistema sin distinguirlos lleva a cientos de flags que nadie se atreve a borrar.
Ejemplo con OpenFeature
OpenFeature define una API neutral de proveedor (LaunchDarkly, Unleash, flagd, ConfigCat…). El código no cambia al cambiar de proveedor:
OpenFeatureAPI api = OpenFeatureAPI.getInstance();
api.setProviderAndWait(new FlagdProvider());
Client flags = api.getClient();
EvaluationContext ctx = new ImmutableContext(solicitud.clienteId(),
Map.of("pais", new Value(solicitud.pais())));
if (flags.getBooleanValue("scoring-v2", false, ctx)) {
return scoringV2.evaluar(solicitud);
}
return scoringV1.evaluar(solicitud);
El valor por defecto (false) se usa si el proveedor no responde: elige siempre el comportamiento seguro.
Buenas prácticas de diseño
- Un punto de decisión: evalúa el flag una vez en el borde y pasa la decisión hacia dentro; evita
if (flag)repartidos por diez clases. - Asignación estable: la misma entidad (cliente) siempre recibe la misma variante durante el experimento.
- Probar ambas ramas en CI mientras el toggle exista.
- Auditoría: quién cambió qué flag y cuándo; en sectores regulados es imprescindible.
Antipatrones frecuentes
- Flags eternos: el código acumula ramas muertas. Pon fecha de expiración y alertas.
- Reutilizar un flag antiguo para otra función: el incidente de Knight Capital (2012) es el ejemplo clásico de lo que puede costar.
- Toggles para ocultar migraciones de datos incompatibles: un flag no revierte un esquema.
Ciclo de vida de un toggle de release
Crear (con dueño y fecha) → desplegado apagado → activo en interno → % progresivo
→ 100 % estable durante N días → eliminar código y flag → cerrar ticket
| Etapa | Responsable | Comprobación |
|---|---|---|
| Creación | Equipo que desarrolla | Registro con tipo, dueño, ticket y fecha de retirada |
| Activación | Producto + equipo | Métricas técnicas y de negocio por variante |
| Estabilización | Equipo | 100 % durante el periodo acordado sin incidentes |
| Retirada | Equipo | Código muerto eliminado, flag borrado del proveedor |
Un job en CI puede listar flags cuya fecha de retirada ya pasó y abrir un ticket o fallar el build.
Probar combinaciones
Con decenas de flags no es posible probar todas las combinaciones. Estrategia práctica:
- Probar cada flag de release en ambos estados con el resto en su valor de producción.
- Una configuración «todo como en producción hoy» y otra «todo lo que se activará en la próxima semana».
- Evitar dependencias entre flags; si existen, documentarlas y probarlas explícitamente.
@ParameterizedTest
@ValueSource(booleans = {true, false})
void evaluaSolicitudConAmbosMotores(boolean scoringV2) {
flags.establecer("scoring-v2", scoringV2); // proveedor en memoria para pruebas
var resultado = servicio.evaluar(solicitudDePrueba());
assertThat(resultado.decision()).isIn(APROBADA, RECHAZADA, REVISION);
}
OpenFeature incluye un proveedor en memoria para pruebas, de modo que no se depende del servicio de flags.
Plataforma propia o servicio
| Opción | Encaja cuando |
|---|---|
| Archivo de configuración / variables | Pocos toggles de release, sin segmentación |
| flagd, Unleash, Flagsmith (open source, autoalojable) | Segmentación y auditoría con control de datos |
| LaunchDarkly, ConfigCat, Statsig (SaaS) | Experimentación avanzada, sin operar infraestructura |
| Plataforma de experimentación (ABsmartly) | Toggles de experimento con análisis estadístico |
Programar contra OpenFeature permite empezar con una opción sencilla y cambiar más adelante sin tocar el código.
Observabilidad
Registra la variante evaluada como atributo en trazas y logs (los hooks de OpenFeature lo facilitan). Así, al investigar un incidente, se puede filtrar por «peticiones con scoring-v2=true» y saber si el problema está ligado a la nueva funcionalidad.
Criterios de implementación
Registra cada flag con tipo, dueño y fecha de retirada. Incluye en la definition of done de una funcionalidad la eliminación del toggle de release. Combínalo con trunk-based development, 1% canary y plataformas de experimentación como ABsmartly.
Continúa en las fuentes
Documentación oficial para verificar detalles y explorar más.