{
 "subtemas": [],
 "tarjetas": [
  {
   "sub": "Comunicación",
   "q": "Message Router / Content-based routing: qué es",
   "a": "Decidir el destino de un mensaje por su CONTENIDO (tipo, atributos): 'eventos de pago → topic pagos; alertas → topic ops'.\nImplementado con filters de subscription (Pub/Sub), routing keys (Rabbit) o el gateway de eventos (Eventarc).\nMantén las reglas declarativas y versionadas — routers con lógica oculta se vuelven indebuggeables.",
   "nivel": "intermedio",
   "clave": false
  },
  {
   "sub": "Comunicación",
   "q": "Splitter / Aggregator (EIP): dividir y recomponer trabajo",
   "a": "Splitter: un pedido grande → N items como mensajes independientes (paralelismo por item).\nAggregator: recolecta los N resultados (correlation por pedido_id) y emite el resultado completo cuando todos llegan (o timeout con parciales).\nEstado del aggregator: Redis/DB con TTL.\nEjemplo clásico: procesar factura línea a línea y consolidar.",
   "nivel": "avanzado",
   "clave": false
  },
  {
   "sub": "Comunicación",
   "q": "Process Manager: el primo serio del orquestador",
   "a": "Máquina de estados distribuida: recibe eventos/comandos, decide próximo paso según estado persistido, emite comandos.\nDiferencia con orquestador simple: maneja MÚLTIPLES instancias del flujo concurrentes, timeouts, reintentos y compensaciones como reglas declarativas.\nImplementaciones: Workflows (GCP), Temporal, Camunda — o tabla de saga propia.",
   "nivel": "avanzado",
   "clave": false
  },
  {
   "sub": "Comunicación",
   "q": "Dead letter processing: automatizar la reparación",
   "a": "El DLQ no es un vertedero: pipeline de reparación — tooling que inspecciona el mensaje + error, permite editar payload y re-publicar (replay) con un click/endpoint.\nMétrica: edad del mensaje más viejo en DLQ; alerta cuando > umbral.\nAuditoría: quién re-publicó qué y cuándo (los mensajes re-procesados marcan retried=true).",
   "nivel": "avanzado",
   "clave": false
  },
  {
   "sub": "Datos y consistencia",
   "q": "Idempotencia con caducidad: el TTL del dedup",
   "a": "La tabla de dedup crece para siempre si no expira: guarda (message_id, processed_at) con purga a 7-30 días (mayor periodo máximo de re-entrega del broker).\nVentana peligrosa: un mensaje re-entregado DESPUÉS de purgar su id se procesa dos veces.\nMitigación: hacer la operación naturalmente idempotente (upsert por entity_id) — el dedup es optimización, no la única defensa.",
   "nivel": "avanzado",
   "clave": false
  },
  {
   "sub": "Datos y consistencia",
   "q": "Soft delete vs hard delete entre servicios",
   "a": "Hard delete en el dueño → consumidores con referencia muerta (FK fantasma). Mejor: eventos de tipo 'eliminado' + soft delete (status=deleted, filtro en query) durante la ventana de sincronización.\nPurga real (GDPR): job que propaga el borrado a todos los read models + logs con tokenización previa.\nLos backups: definir retención y exclusiones desde el diseño.",
   "nivel": "intermedio",
   "clave": false
  },
  {
   "sub": "Datos y consistencia",
   "q": "Sagas y validación de negocio: rechazo asincrónico",
   "a": "En saga, el 'no' llega tarde (pago rechazado 3s después de crear el pedido).\nDiseño: estados intermedios visibles (PENDING_PAYMENT), el cliente ve el progreso, compensación automática al rechazo, y notificación final (push/email).\nProhibido: crear el pedido COMPLETO y 'borrarlo' si falla — estados y compensaciones, no deshacer silencioso.",
   "nivel": "intermedio",
   "clave": false
  },
  {
   "sub": "Datos y consistencia",
   "q": "Data ownership ambiguity: quién es dueño de 'cliente'",
   "a": "Típico bloqueo: pedidos necesita datos del cliente, marketing también, soporte también.\nRegla: la ENTIDAD maestra (fuente de verdad del registro) tiene UN dueño (servicio identidad/clientes); los demás mantienen VISTAS locales (nombre, email) actualizadas por eventos.\nCambios al modelo maestro: propuesta al dueño, no 'un updatecillo' directo a su tabla.",
   "nivel": "intermedio",
   "clave": false
  },
  {
   "sub": "Resiliencia",
   "q": "Circuit breaker + caché: el combo de lectura resiliente",
   "a": "Lectura crítica (precios): 1) caché L1 local, 2) Redis, 3) BD. Si todo falla → último valor conocido con timestamp ('precio al 14:32').\nEl breaker protege la BD de la tormenta; el serve-stale mantiene la app útil.\nHeader X-Cache: STALE para trazabilidad.\nResultado: la caída de una dependencia de lectura se vuelve invisible para el usuario final.",
   "nivel": "intermedio",
   "clave": false
  },
  {
   "sub": "Resiliencia",
   "q": "Budget de error en operaciones: cuándo congelar releases",
   "a": "Error budget del mes consumido > 80% → congelar features no críticas, solo fixes de confiabilidad.\nAutomatizar: el dashboard muestra el presupuesto; la política está escrita (quién decide, qué cuenta).\nEvita la discusión eterna '¿seguimos lanzando?' en pleno incidente — la matemática decide.",
   "nivel": "intermedio",
   "clave": false
  },
  {
   "sub": "Plataforma y despliegue",
   "q": "gRPC interno: contratos y mejores prácticas entre servicios",
   "a": "Protos en repos compartido (api-definitions) con versioning semántico por paquete (pedidos.v1).\nDeadline SIEMPRE propagado; keepalive configurado; status codes gRPC mapeados a errores de negocio (FAILED_PRECONDITION vs INTERNAL).\nInterceptors: auth (JWT), tracing, recovery — infra común en librería interna.\nReflection habilitada en staging para debug con grpcurl.",
   "nivel": "intermedio",
   "clave": false
  },
  {
   "sub": "Plataforma y despliegue",
   "q": "API interna vs externa: por qué NO exponer tus protos/entidades",
   "a": "API externa: REST/JSON estable, versionada para terceros, auth de usuarios.\nAPI interna: gRPC/protobuf, puede evolucionar más rápido, auth de servicios (mTLS/tokens).\nCompartir el mismo contrato = los cambios internos rompen a externos (o external congelan tu evolución).\nTraducción en el edge (gateway/BFF) — el costo extra compra libertad interna.",
   "nivel": "intermedio",
   "clave": false
  },
  {
   "sub": "Plataforma y despliegue",
   "q": "Multi-region de un microservicio: el checklist concreto",
   "a": "Datos: estrategia por BD (replica global o por región + partición de usuarios).\nTráfico: LB global, deployment en ambas regiones.\nEstado: stateless (sesiones/caché compartidos o regionales).\nDeploy: pipeline despliega ambas con canary independiente por región.\nDR probado: drill que apaga una región y mide el impacto real.",
   "nivel": "avanzado",
   "clave": false
  },
  {
   "sub": "Operación y organización",
   "q": "Documentación viva de un servicio: el set mínimo",
   "a": "README (qué hace, cómo correr), runbook (alertas y acciones), ADRs (decisiones), diagrama C4 container, contrato API (spec generado), SLOs y dashboards linkeados, ownership (equipo + canal).\nTodo EN EL REPO o linkeado del catálogo.\nTest de vida: si un alerta enlaza al runbook correcto, la doc vive; si nadie la actualizó en un año, está muerta.",
   "nivel": "intermedio",
   "clave": false
  },
  {
   "sub": "Operación y organización",
   "q": "Estimación de carga para un servicio nuevo (metodología)",
   "a": "1) Volumen esperado del negocio (usuarios, transacciones/día). 2) Pico: promedio x factor horario (10-50x en flashes). 3) Por request: tamaño y count de queries/llamadas. 4) Capacidad: throughput por réplica medido en load test (no asumido). 5) Réplicas = pico/throughput x margen 2x.\nRevisar con datos reales al mes 1 — toda estimación inicial está mal en algo.",
   "nivel": "intermedio",
   "clave": false
  },
  {
   "sub": "Operación y organización",
   "q": "Game days: ensayar incidentes con guion",
   "a": "Escenario planificado (caída de Redis, pérdida de región, pico 5x), fecha agendada, roles reales de on-call, observadores que anotan tiempos de detección/mitigación.\nResultado: gaps concretos (alerta faltante, runbook inexistente, acceso sin permiso) → backlog de confiabilidad.\nFrecuencia: trimestral por equipo de on-call. La primera vez SIEMPRE se descubre algo vergonzoso — mejor en un game day.",
   "nivel": "intermedio",
   "clave": false
  },
  {
   "sub": "Operación y organización",
   "q": "Cómo justificar inversión en confiabilidad con números",
   "a": "Traduce a dinero: incidentes del último año × duración × revenue/minute afectado = costo de NO invertir.\nComparar: precio de la mejora (equipo/infra) vs pérdida evitada + churn de clientes grandes.\nAgrega riesgo regulatorio si aplica (multas).\nEl SRE budget se aprueba con historia de incidentes cuantificada, no con 'sentimos que faltan pruebas'.",
   "nivel": "avanzado",
   "clave": false
  },
  {
   "sub": "Fundamentos y decisiones",
   "q": "Arquitectura evolutiva: fitness functions",
   "a": "Métricas automatizadas que validan UNA decisión arquitectónica continuamente: ArchUnit (dependencias entre módulos), contract tests (acoplamiento de APIs), performance test en CI (presupuesto de latencia), security scans (postura).\nSi la función falla, la deriva arquitectónica se detiene en CI, no en producción.\nEs como tener un arquitecto revisando cada commit.",
   "nivel": "avanzado",
   "clave": false
  },
  {
   "sub": "Fundamentos y decisiones",
   "q": "Escenario: «startups rápido: ¿empezamos con microservicios?» — respuesta honesta",
   "a": "No. Empieza monolito modular: 1 deploy, 1 BD, equipo pequeño va rapidísimo.\nDisciplina barata que paga después: módulos por dominio, sin joins cruzados entre módulos, eventos internos desde el inicio, CI por módulo.\nCuando un módulo CRECE y tiene dueño propio → extracción mecánica (esa ruta ya se anduvo).\nLa velocidad inicial manda: el dominio no descubido se corta mal siempre.",
   "nivel": "intermedio",
   "clave": false
  }
 ]
}