Common Pitfalls
Reconocer problemas en el razonamiento
Un pitfall de System Design es, en el Atlas, una forma recurrente de razonar, encuadrar o decidir que tiende a ocultar consecuencias arquitectónicas importantes, representar mal la evidencia o producir riesgo evitable bajo condiciones frecuentes. Es una definición editorial de trabajo: el término es amplio e informal, sin una definición única para toda la literatura.
La unidad de revisión es el razonamiento situado. Microservices, Kafka, Kubernetes, Redis, Serverless y bases relacionales no son errores en sí mismos. Una decisión individualmente razonable puede resultar problemática cuando cambia el contexto, se combina con otra o desplaza costos que nadie examinó. El objetivo es recuperar preguntas y corregir compromisos, no identificar «malos arquitectos».
Un architectural-pattern ofrece conocimiento reutilizable; un pitfall señala una dificultad recurrente de aplicación o evaluación. Un defecto es un incumplimiento concreto que puede existir sin ese patrón de razonamiento. Una constraint real limita opciones; un trade-off reconocido puede aceptarse deliberadamente. No llamar pitfall a cualquier consecuencia negativa o decisión que otra persona habría tomado de modo distinto.
Tampoco todo pitfall es un anti-pattern. La literatura de antipatterns documenta soluciones recurrentes perjudiciales y formas de corregirlas; véase la presentación de Phillip Laplante. Aquí el alcance incluye errores de encuadre, evidencia y proceso que no constituyen necesariamente una solución arquitectónica recurrente completa.
Encuadre, necesidades y supuestos
La siguiente agrupación es organización del Atlas para navegación, no una taxonomía industrial. Los casos se superponen: una respuesta tecnológica prematura puede distorsionar requisitos, estimaciones y evaluación al mismo tiempo. Los canónicos enlazados conservan las definiciones; este documento muestra fallos al utilizarlas.
Empezar por la solución o justificar después el producto
«Necesitamos Microservices» antes de aclarar problema y alcance cierra opciones sin saber qué necesidad resuelve. La familiaridad reduce incertidumbre inmediata y hace tentadora esa respuesta. requirements-to-architecture permite preguntar qué resultado falta; design-process exige conectar candidatos con drivers antes de comprometer estructura.
Technology-first puede aparecer incluso después de entender el problema: el equipo elige un producto y remodela requisitos para justificarlo. Capacidades comerciales sustituyen necesidades, y la comparación se limita a marcas. Preguntar qué decisión arquitectónica permanece si se oculta el nombre del producto ayuda a recuperar alternativas. Una tecnología impuesta por contrato sigue siendo contexto legítimo.
Profiles, distribución y escala como respuestas automáticas
Escribir «arquitectura: Microservices» no declara fronteras, autoridad, interacción, deployment ni coordinación. architecture-profiles aporta candidatos; high-level-design necesita decisiones situadas. Del mismo modo, System Design no exige distribución: un deployable puede atender los drivers, y Monolith no representa inmadurez.
Diseñar para millones de usuarios, regiones globales, sharding y queues sin demanda relevante puede agregar compromisos difíciles de sostener. scaling necesita workload y límites, no ambición abstracta. Preguntar qué crecimiento comprometido podría invalidar la opción sencilla antes de preparar mecanismos para futuros hipotéticos.
Adjetivos, prioridades y preferencias endurecidas
«Rápido», «disponible» o «mantenible» parecen acuerdos mientras cada participante imagina una situación distinta. quality-attribute-scenarios permite precisar lo necesario para comparar, sin exigir números ficticios. Tratar cada requisito como driver también dispersa atención: architectural-drivers y architectural-significance ayudan a seleccionar influencias y consecuencias importantes.
«Siempre usamos PostgreSQL» puede describir preferencia, experiencia o política revisable. Antes de convertirlo en constraint, verificar autoridad, vigencia y alcance. Las habilidades reales pueden limitar opciones sin ser inmutables. constraints mantiene esa distinción y evita descartar candidatos por comodidad disfrazada de obligación.
Supuestos ocultos completan artificialmente el problema: usuarios uniformes, consumidores que actualizan de inmediato, pico igual a media por diez o SLA del proveedor equivalente al del sistema. Hacer visible origen y condición de revisión mediante estimation permite descubrir temprano qué compromiso depende de información débil.
Estructura, interacción y estado
Dibujos que sustituyen decisiones
Una vista puede omitir deployment, autoridad, flujo o fallos importantes; no necesita mostrar todo, pero sí servir a la pregunta. Acumular diagramas tampoco garantiza coherencia. En high-level-design, contrastar la vista con un escenario revela qué decisión falta mejor que contar cajas.
Responsabilidad lógica, servicio, proceso, container y deployment unit no son equivalentes. components, decomposition y deployment permiten aclarar qué representa cada elemento. Dibujar fronteras primero y buscarles responsabilidades después favorece divisiones arbitrarias. boundaries y modularity recuperan decisiones protegidas y cambios que deberían permanecer locales.
Más servicios no demuestran mejor modularidad: pueden conservar acoplamiento de cambios y operación. Una flecha «calls» también puede ocultar local/remoto, espera, contrato, resultado y fallo. connectors, communication e interfaces orientan qué semántica significativa necesita explicitarse, sin etiquetar exhaustivamente cada detalle.
Confundir almacenamiento con autoridad
Database per service no crea por sí mismo data-ownership, ni una base compartida implica autoridad compartida. El problema aparece cuando varias unidades escriben el mismo estado lógico sin reglas, nadie gobierna sus invariantes o reporting se convierte accidentalmente en escritor.
Una copia de lectura puede conservar datos sin recibir autoridad sobre su significado. Preguntar quién valida cada transición y quién puede corregirla es más útil que contar bases. En Commerce, mover Payments a otro proceso no autoriza automáticamente a Orders a modificar pagos; esa ambigüedad exige corregir contrato o acceso, no necesariamente reemplazar todo el sistema.
Async, mensajes y coordinación confundidos
Trabajo async puede usar ejecución diferida sin constituir event-driven-architecture. Un mensaje tampoco equivale siempre a evento o command: conservar intención y semántica del intercambio mediante communication y execution-model. Los términos no se vuelven intercambiables porque viajen por el mismo broker.
Choreography cambia dónde se expresa coordinación, no elimina el resultado comercial conjunto. coordination permite preguntar quién conoce progreso, orden y recuperación. Un diagrama solo del camino feliz puede esconder pago desconocido, reserva expirada o notificación fallida. deep-dives selecciona esos caminos cuando amenazan compromisos, sin investigar todos los fallos imaginables.
Tratar red como memoria local y retry como garantía
Una llamada remota añade condiciones distintas de una llamada local. Waldo y coautores explican diferencias de latencia, concurrencia y fallo parcial en A Note on Distributed Computing. Ocultarlas detrás de una interface no las elimina del diseño.
timeout necesita razonamiento explícito sobre límites y resultado incierto. retry sin considerar persistencia del fallo, idempotency, demora y demanda downstream puede agravar un incidente. Google SRE, Addressing Cascading Failures documenta amplificación por retries. Preguntar qué ocurrió realmente y qué repetición es segura antes de añadir intentos.
Operación, capacidad y evidencia
Delegar garantías que el sistema todavía debe sostener
Cloud y servicios gestionados trasladan responsabilidades, pero no entregan automáticamente disponibilidad de extremo a extremo. cloud-migration y operability ayudan a revisar dependencias, diagnóstico y recuperación. Un compromiso del proveedor no demuestra que el checkout conserve la respuesta que el negocio necesita.
Agregar réplicas solo ayuda si el recurso limitante crece de ese modo. Una quota externa, lock o estado compartido puede seguir dominando. Una queue puede absorber ráfagas sin crear capacidad downstream; revisar backpressure y queue-management cuando corresponda. Cache tampoco es mala por definición: introducirla sin necesidad y semántica examinadas agrega preguntas de vigencia, invalidación, memoria y fallo que el dibujo inicial puede esconder.
Calcular números que aparentan certeza
Media diaria no representa pico, ni media de latencia equivale a p99. Obtener 115,7407407 requests/s de entradas aproximadas no mejora la evidencia. Multiplicadores de pico, headroom o utilización pueden ser hipótesis locales, pero no leyes. estimation conserva unidades, rangos y condiciones.
También falla la cuenta correcta desconectada de una decisión. Calcular storage o bandwidth porque aparece en un template agrega ruido si nada depende del resultado. Preguntar qué alternativa cambiaría al variar la entrada y qué observación permitiría reemplazar el supuesto.
Pruebas cómodas y comparaciones sesgadas
Un benchmark con otro workload, datos o ambiente no establece superioridad para el escenario actual. Un prototipo que conecta con un proveedor no prueba seguridad, operación, escala y mantenimiento. deep-dives ayuda a delimitar qué evidencia aporta cada prueba y qué obligación permanece abierta.
Una matriz ponderada no convierte Microservices 87/100 en verdad arquitectónica. trade-off-analysis expone pesos arbitrarios, doble conteo e incertidumbre. Presentar la opción favorita cuidadosamente y una alternativa ingenua produce un strawman. Una decisión significativa merece candidatos creíbles, sin exigir exploración exhaustiva para elecciones triviales y reversibles.
Mejorar una parte y trasladar el costo
Maximizar aislamiento puede aumentar costo y operación; autonomía de release puede coexistir con coordinación intensa por datos y contratos. quality-attribute-trade-offs y systems-thinking permiten seguir consecuencias más allá del componente favorecido. Una mejora local no demuestra mejora del resultado conjunto.
Contar solo implementación inicial oculta soporte, incidentes, mantenimiento, formación, migración y retirada. cost-efficiency conecta recursos con resultados útiles. Preguntar quién sostiene cada responsabilidad y durante cuánto tiempo, especialmente cuando el beneficio aparece tarde y el costo comienza hoy.
Evolución y proceso de decisión
Borrar el pasado en el diagrama objetivo
En brownfield existen comportamiento valioso, datos, integraciones y consumidores, incluso desconocidos. legacy-systems conserva ese contexto; refactor-vs-rewrite evita tratar una reescritura como reset de complejidad comercial. Una implementación nueva también necesita transición y puede introducir deuda y riesgo propios.
migration-strategy pregunta cómo llegar, con autoridad y compatibilidad en estados intermedios. Desplegar el camino nuevo no significa completar data-migration ni retirar escritores, consumidores, soporte o infraestructura antiguos. Antes y después de implementar, buscar evidencia de esos usos permite corregir secuencia sin descartar necesariamente el objetivo.
Lo temporal sin salida y lo deprecated sin responsable
Adapters, dual writes y APIs anteriores pueden volverse permanentes por omisión. Declarar responsable, condición de salida y evidencia para retirarlos conserva intención; technical-debt y architecture-erosion permiten examinar el desajuste cuando cambia esa intención. No todo mecanismo duradero es una violación si se acepta y gobierna explícitamente.
deprecation no elimina ownership, soporte ni guía de migración. sunsetting necesita condiciones y obligaciones de cierre. Marcar un componente como viejo y dejar de atenderlo puede crear riesgo mientras consumidores legítimos siguen dependiendo de él.
Documentar o investigar sin converger
Documentar todo y hacer Deep Dive de cada componente consume tiempo sin atender necesariamente el riesgo decisivo. Fairbanks propone seleccionar técnicas y reevaluar riesgos, en lugar de aplicar siempre un paquete fijo de actividades. Risk-Centric Model. Más páginas no equivalen a mejor arquitectura.
El extremo opuesto es no revisar nunca: drivers, supuestos y evidencia cambian. evolutionary-architecture y fitness-functions ayudan a conservar feedback relevante. El análisis interminable también falla: design-process necesita converger para construir y contrastar el próximo alcance. Un timebox limita costo, sin certificar suficiencia.
Corregir sin culpar ni reiniciar todo
Muchos casos surgen de información incompleta, presión, incentivos locales o palabras ambiguas. En una revisión, describir la consecuencia oculta y la pregunta que falta; buscar evidencia proporcional y corregir primero el compromiso afectado. Evitar «best practice» como autoridad sin problema, driver y condiciones.
Antes de implementar, recorrer un escenario y declarar supuestos puede revelar la omisión. Después, un incidente, una medición o un cambio difícil puede refutar lo supuesto. Conservar esa observación, revisar la razón original y probar una corrección acotada permite aprender sin declarar inválido todo lo construido ni repetir la misma promesa sin evidencia nueva.
design-exercises permite practicar esa lectura: detectar dónde una propuesta asumió autoridad, confundió frontera o estimó sin propósito, y revisarla con información nueva. Los pitfalls son lentes seleccionadas, no cien casillas obligatorias. Reconocer uno abre investigación; no demuestra automáticamente que toda la arquitectura deba sustituirse.