Tema representativo de entrevista

Entrevista de diseño de sistemas: ¿Cómo diseñarías un sistema de validación con tráfico espejo (Shadow Traffic)?

Diseño de sistemasDifícil
Equipo editorial de Offer.ccPublicado Actualizado

Pregunta

Un equipo quiere validar un nuevo backend contra solicitudes reales de producción antes de cambiar el tráfico. ¿Cómo duplicarías las solicitudes, protegerías las credenciales y los efectos secundarios, compararías las respuestas, limitarías la tasa de reproducción y decidirías si la nueva versión es segura?

Planteamiento y alcance

Diseña un sistema de tráfico espejo (shadow-traffic) para un servicio que recibe 20,000 solicitudes por segundo. La solicitud principal debe mantener su latencia p99 existente, mientras que la versión espejo puede retrasarse. El sistema debe realizar muestreo por endpoint, persistir suficiente evidencia para reproducir una discrepancia, comparar campos de respuesta significativos y nunca permitir que una solicitud duplicada envíe un pago, un correo electrónico u otro efecto secundario externo.

La distinción central es la duplicación de solicitudes a nivel de aplicación (request mirroring), no la captura de paquetes. Un balanceador de carga puede reenviar una copia de tipo "disparar y olvidar" (fire-and-forget) a un backend espejo, mientras que la respuesta principal sigue siendo autoritativa. La duplicación de paquetes de red tiene diferentes objetivos y encapsulación, por lo que no es un sustituto de una ruta de reproducción consciente de la aplicación.

Qué evalúa el entrevistador

El entrevistador busca un entorno de comparación seguro, no un segundo servicio de producción con tráfico copiado. Las respuestas sólidas preservan la ruta de latencia principal, eliminan credenciales, aíslan escrituras, hacen que el muestreo sea reproducible y explican por qué una diferencia byte por byte a menudo es incorrecta.

Indagarán sobre qué sucede cuando la cola de captura está llena, cuando la versión espejo es más lenta, cuando una respuesta contiene marcas de tiempo y cuando la solicitud principal ya realizó una escritura. Trata cada uno de estos casos como una política explícita.

Aclaraciones que cambian el diseño

  • ¿Las solicitudes son de solo lectura? Las solicitudes de solo lectura se pueden reproducir directamente; las solicitudes mutables necesitan un entorno aislado (sandbox), stubs o una identidad sintética.
  • ¿La comparación es exacta o semántica? La comparación exacta es adecuada para JSON determinista; las máscaras o comprobaciones de invariantes se adaptan a marcas de tiempo e IDs generados.
  • ¿Los cuerpos capturados pueden contener datos personales? Si es así, anonimiza antes de almacenar, cifra las referencias y define la retención y la auditoría de acceso.
  • ¿El objetivo es la corrección en la migración, la latencia o la capacidad? La métrica y la política de muestreo cambian según el objetivo.

Estructura para una respuesta de 30 segundos

“Capturaría una solicitud autenticada después de la autorización pero antes de las escrituras externas, sanearía secretos y datos personales, y encolaría una muestra determinista de forma asíncrona. La respuesta principal sigue siendo autoritativa. Workers aislados de shadow reproducen contra un sandbox con una tasa limitada y una credencial separada. Un servicio de diferencias compara el estado, los campos seleccionados, los invariantes y la latencia, ignorando el no determinismo declarado. Las capturas durables permiten la investigación, pero el desbordamiento de la cola descarta la copia espejo en lugar de ralentizar a los usuarios. La promoción requiere un presupuesto definido de divergencia y error, además de comprobaciones de que las escrituras, la privacidad y la capacidad del shadow sean seguras.”

Diseño paso a paso

1. Capturar sin afectar la ruta crítica

Coloca un hook de captura después de la autenticación y autorización para que el sistema conozca el endpoint y la política del tenant, pero antes de cualquier llamada externa irreversible. Copia solo los campos necesarios para el shadow. Elimina la autorización, cookies, tokens de usuario y datos de pago; reemplázalos con una credencial de shadow de corta duración o una identidad de prueba fija.

Publica un MirroredRequest que contenga un ID de solicitud, trace ID, endpoint, encabezados saneados, referencia al cuerpo, hora de captura, versión de destino y versión de la configuración de muestreo. La operación de encolado debe tener un tiempo de espera acotado. Si el búfer local o la cola durable están llenos, registra una métrica de descarte y devuelve la respuesta principal.

2. Hacer que el muestreo sea reproducible

Aplica un hash a un ID de solicitud o trace ID estable y compáralo con la tasa de muestreo configurada. Esto mantiene las reintentos y las investigaciones de forma determinista. Aplica un segundo bucket de tokens por endpoint y tenant para limitar las RPS espejo; se aplica el valor más bajo entre el porcentaje y el presupuesto de tokens.

Conserva la versión de la configuración de muestreo con cada captura. Un informe posterior podrá distinguir una divergencia real de una regla de muestreo modificada.

3. Reproducir en un entorno aislado

Los workers leen la cola durable y llaman al destino shadow con un tiempo de espera corto. El shadow debe usar una base de datos separada o un fixture sin transacciones, utilizar stubs para proveedores de pago y correo electrónico, y deshabilitar callbacks salientes. Para rutas de lectura, una réplica de solo lectura o una instantánea saneada suele ser más segura que el almacenamiento de producción.

La entrega al menos una vez (at-least-once) es aceptable para la cola de captura porque la reproducción está etiquetada por ID de solicitud. El worker registra SHADOW_ERROR, DROPPED o COMPLETED; un tiempo de espera en el shadow nunca reintenta indefinidamente ni bloquea la solicitud principal.

4. Comparar respuestas por significado

Compara primero los códigos de estado. Para respuestas JSON exitosas, elimina los campos declarados explícitamente como no deterministas, luego compara rutas seleccionadas o hashes de cuerpos canonicalizados. Añade invariantes de dominio como “el total no es negativo” o “el usuario devuelto pertenece al tenant solicitado”. Compara la latencia por separado; una respuesta puede ser correcta pero demasiado lenta para su promoción.

Almacena ambos hashes, las rutas con diferencias, la latencia principal y de shadow, la versión del despliegue y una referencia de solicitud de muestra. No almacenes cuerpos sensibles sin procesar en el informe.

5. Definir compuertas de promoción

Crea umbrales antes de iniciar la reproducción: tasa de divergencia, tasa de error de shadow, regresión de latencia, antigüedad de la cola y fallos de anonimización. Segmenta los informes por endpoint, nivel de tenant, región y clase de respuesta; una tasa global en verde puede ocultar un endpoint de pago defectuoso.

Usa una ventana deslizante con cantidades mínimas de muestra. Un umbral de divergencia del 1% es una política de ejemplo, no una regla universal. La promoción también requiere cero efectos secundarios inseguros, una capacidad de shadow aceptable y ejemplos revisados para cada discrepancia de gravedad alta.

6. Operar y recuperar

Pausa la reproducción sin deshabilitar la captura cuando el shadow esté sobrecargado. Haz expirar las capturas de acuerdo con la política de privacidad y audita el acceso a las referencias de solicitudes almacenadas. Si se revierte una versión shadow, mantén sus informes vinculados al despliegue para que los análisis posteriores no mezclen versiones.

Prueba la pérdida de colas, capturas duplicadas, configuraciones obsoletas, fuga de credenciales, intentos de efectos secundarios, campos no deterministas, tiempos de espera de shadow y fallos regionales. El criterio de éxito es que el servicio principal permanezca dentro de su SLO mientras el shadow produce evidencia procesable y reproducible.

Respuesta de ejemplo de alta calidad

“Construiría un hook de duplicación consciente de la aplicación después de la autenticación y antes de las escrituras externas. Este elimina credenciales reales y campos sensibles, almacena una referencia al cuerpo y realiza un muestreo determinista por trace ID. La ruta principal nunca espera al shadow; una cola acotada puede descartar trabajo de duplicación bajo presión.

“Workers aislados reproducen contra una versión shadow con una identidad separada, base de datos independiente y proveedores sustituidos por stubs. Cada reproducción tiene un ID de solicitud y un tiempo de espera. El servicio de comparación verifica el estado, rutas JSON seleccionadas, invariantes de dominio y latencia, ignorando solo los campos declarados no deterministas. Los informes retienen hashes, rutas con diferencias, versiones y ejemplos saneados.

“Antes de promocionar, establecería compuertas a nivel de endpoint para divergencia, errores, latencia, antigüedad de la cola y fallos de privacidad, requeriría una muestra mínima e inspeccionaría diferencias graves. Los endpoints mutables necesitan un sandbox o son excluidos. Validaría el desbordamiento de la cola, duplicados, eliminación de credenciales, efectos secundarios y fallos regionales mientras demuestro que el SLO principal no se ve afectado.”

Errores comunes

  • Error → Falla → Solución: Reproducir credenciales de producción → las llamadas shadow pueden filtrar datos o mutar sistemas reales → eliminar secretos y usar identidades y proveedores aislados.
  • Error → Falla → Solución: Esperar al shadow antes de responder → las pruebas de migración aumentan la latencia del usuario → encolar de forma asíncrona y descartar trabajo de duplicación bajo presión.
  • Error → Falla → Solución: Comparar únicamente cuerpos sin procesar → las marcas de tiempo y los IDs generados crean falsos positivos → canonicalizar y comparar campos declarados junto con invariantes.
  • Error → Falla → Solución: Duplicar cada solicitud indefinidamente → el almacenamiento, la privacidad y la capacidad del shadow crecen sin límite → usar muestreo determinista, cuotas, retención y auditorías de acceso.
  • Error → Falla → Solución: Usar una única tasa global de divergencia → un endpoint crítico pequeño puede fallar dentro de un agregado en verde → establecer compuertas por endpoint, tenant, región y gravedad.

Preguntas de seguimiento y respuestas

¿Qué pasa si el endpoint escribe en una base de datos?

Enruta el shadow a una base de datos desechable o a un stub de transacción, y reemplaza las llamadas externas con simulaciones (fakes) que registren la intención. Si la escritura no se puede aislar, excluye el endpoint y declara la brecha de cobertura en lugar de fingir que el resultado es seguro.

¿Qué pasa si la cola de captura está llena?

Aplica fail-open para la solicitud principal: descarta la copia duplicada, incrementa una métrica etiquetada y genera una alerta cuando se exceda el presupuesto de descartes. Aplicar contrapresión (backpressure) sobre la solicitud principal invalidaría la propiedad principal de seguridad.

¿Cómo manejas la información de identificación personal?

Clasifica los campos en el momento de la captura, anonimiza o tokeniza antes del almacenamiento durable, cifra las referencias a los cuerpos, limita la retención y audita el acceso. El hash de una carga útil sensible aún puede ser identificable, por lo que no es automáticamente seguro.

¿Puede la duplicación de paquetes reemplazar la duplicación a nivel de aplicación?

No. La duplicación de paquetes copia el tráfico de red hacia un destino de análisis, mientras que la duplicación a nivel de aplicación comprende la semántica de los endpoints, las credenciales, las políticas de tenant y la comparación de respuestas. Usa la duplicación de paquetes para inspección de red y una ruta consciente de la aplicación para validación de comportamiento.

Fuentes públicas

Preguntas relacionadas

Herramienta de entrevista relacionada

Usa Resolver para una respuesta de diseño de sistemas

Aclara primero los requisitos y luego avanza a través de la escala, la arquitectura, la elección de componentes y las compensaciones (trade-offs).

Ver la herramienta