Curso exprés · No. 03
Rara vez inventás una arquitectura. La reconocés: qué forma conocida encaja con el problema — y qué precio cobra esa forma.
17 patrones · un diagrama por patrón · resumen al final
Un patrón es una respuesta probada a un problema que se repite en miles de sistemas. Cada patrón tiene un nombre — y casi siempre es un nombre en inglés, el que buscás en la documentación y el que se usa en las entrevistas.
Un patrón es un nombre para una respuesta, no una regla
En el ajedrez no reinventás la apertura en cada partida. Reconocés «esto es una Siciliana» y ya sabés hacia dónde suele llevar.
Patrón de arquitectura (architectural pattern) = problema que se repite + forma probada de resolverlo + precio conocido. Cuando decís «los servicios necesitan reaccionar a lo que pasa en otro lado», eso ya es un problema resuelto y con nombre — el patrón Event-driven architecture. Conocer el catálogo significa dejar de inventar y empezar a elegir.
Patrones de arquitectura ≠ patrones de diseño
Un patrón de diseño es cómo acomodás los muebles en una habitación. Un patrón de arquitectura es el plano de toda la casa.
Los patrones de diseño (design patterns) — Factory, Observer, Strategy — viven dentro del código de un módulo. Los patrones de arquitectura deciden qué «cajas» grandes hay en el sistema y qué líneas las unen: qué se despliega por separado, quién le habla a quién, dónde viven los datos. Este curso es sobre los planos, no sobre los muebles.
Mapa: 17 patrones en seis grupos
Un mapa del metro: primero ves las líneas enteras, después recorrés las estaciones.
Todos los patrones del curso se dividen en seis grupos. Cada grupo responde su propia pregunta: cómo estructurar una aplicación, hacia dónde apuntan las dependencias, cómo partir el sistema, cómo se comunican las piezas, cómo guardar la verdad en los datos y qué formas hacen falta para problemas raros.
Cómo leer cada patrón
Un pasaporte: los mismos campos para todos, por eso es fácil compararlos.
Cada patrón de acá en adelante tiene lo mismo: nombre en inglés (aprendetelo — es el término), una imagen de la vida real, un diagrama y una ficha con campos: problema (qué duele), idea (cómo lo resuelve), ejemplo, coste (qué pagás), cuándo usarlo y relaciones con otros patrones. La regla principal: no existe el mejor patrón — existe el que encaja, y cada uno tiene una factura que hay que leer antes de firmarla.
No elegís el patrón famoso. Elegís aquel cuyo precio podés pagar.
La mayoría de los sistemas empiezan como una única aplicación desplegable. Los primeros tres patrones son sobre cómo organizarla por dentro para que no se convierta en barro.
Layered Architecture — arquitectura en capas
Un restaurante: el salón toma los pedidos, la cocina cocina, la despensa almacena. El mozo no cocina, el chef no baja al sótano — cada uno habla solo con la capa de abajo.
El patrón más común. El código se parte en capas (layers) horizontales, y la request las atraviesa de arriba hacia abajo. Cada capa conoce solo a la capa de abajo.
- Problema
Todo el código en una pila: cambiar la interfaz rompe el acceso a la base.
- Idea
Repartir el código en pisos: presentación, lógica de negocio, acceso a datos, base de datos.
- Ejemplo
Una app web:
Controllerllama aService, este aRepository, este a Postgres.- Coste
Todo se despliega como una sola pieza; un cambio chico = redesplegar todo.
- Cuándo usarlo
- Casi siempre, como forma inicial de una aplicación.
- Relaciones
Base del Modular Monolith; dentro de las capas se suele aplicar Hexagonal.
Modular Monolith — monolith modular
Un edificio de departamentos: un solo techo y una sola entrada, pero cada departamento tiene sus propias paredes y su puerta. No atravesás el dormitorio del vecino para llegar a la escalera.
Sigue siendo una sola aplicación, pero por dentro está partida en módulos (modules) según el negocio — facturación, catálogo, cuentas. Los módulos hablan solo a través de una interfaz pública y no meten la mano en las tablas ajenas.
- Problema
El monolith se vuelve una «gran bola de barro»: todo depende de todo.
- Idea
Partir por módulos de negocio con interfaces claras, pero desplegar como una sola pieza.
- Ejemplo
El módulo
catalogllama solo a las funciones públicas debilling, no a sus tablas.- Coste
Hace falta disciplina con los límites (es fácil romperlos si no los controla una herramienta).
- Cuándo usarlo
El default correcto para casi todos — la claridad de los microservicios sin la red.
- Relaciones
Crece de forma natural hacia Microservices: un módulo se saca a un servicio cuando hace falta.
MVC / MVVM — mantené la pantalla lejos del cerebro
Un teatro: el guion, los actores con el director y el escenario con las luces son trabajos distintos. Cambiás la escenografía sin reescribir la obra.
Estos patrones ponen una pared entre la interfaz y los datos con sus reglas, para que un cambio en cómo algo se ve no rompa lo que hace.
- Problema
La lógica está desparramada por las pantallas; cambiar el diseño = reescribir las reglas.
- Idea
Model — datos y reglas, View — lo que se muestra, Controller (o ViewModel) — el pegamento entre los dos.
- Ejemplo
Django y Rails están construidos sobre MVC; las apps móviles y web ricas, sobre MVVM, donde el ViewModel guarda el estado de la pantalla.
- Coste
En pantallas grandes el «pegamento» crece; hay que cuidar que la lógica no se filtre a la View.
- Cuándo usarlo
- Cualquier aplicación con interfaz.
- Relaciones
- Son las capas de Layered, aplicadas a la UI.
Un monolith no es un quilombo. Un quilombo es un monolith sin paredes internas.
Dos patrones, una idea: las reglas de negocio están en el centro y no saben nada del framework, la base de datos ni la web. Todo lo técnico está afuera y se enchufa al núcleo.
Hexagonal Architecture — puertos y adaptadores
Una consola de juegos con puertos estándar. Al juego no le importa qué enchufaste — un joystick, un volante o un palo de arcade; solo lee «input».
El núcleo con la lógica de negocio declara puertos (ports) — interfaces como «guardar un pedido» o «cobrar». Afuera, los adaptadores (adapters) implementan esos puertos para una tecnología concreta. Los driving adapters llaman al núcleo (API HTTP, CLI, tests), los driven adapters son llamados por el núcleo (base de datos, pasarela de pagos, email).
- Problema
La lógica de negocio quedó pegada al framework y a la base — imposible de testear y de cambiar.
- Idea
El núcleo habla solo con puertos (interfaces); la tecnología vive en los adaptadores.
- Ejemplo
Puerto
OrderRepository: en producción, un adaptador sobre Postgres; en los tests, una lista en memoria.- Coste
- Más interfaces y archivos; para un CRUD diminuto es demasiado.
- Cuándo usarlo
Hay reglas de negocio de verdad que tienen que sobrevivir a cambios de tecnología.
- Relaciones
- Clean / Onion — la misma idea, dibujada con círculos.
Clean / Onion Architecture — las dependencias apuntan hacia adentro
Una cebolla: el corazón en el centro, capas alrededor. Podés pelar la piel sin dañar el corazón — y el corazón no depende de la piel.
El mismo principio en forma de círculos. En el centro, las entidades (entities); alrededor, los casos de uso (use cases); después, los adaptadores; afuera, los frameworks y la base de datos. La regla principal — la dependency rule: cada flecha de dependencia apunta hacia el centro.
- Problema
Cambiar de framework o de base de datos obliga a reescribir la lógica de negocio.
- Idea
Dependency rule: los círculos de adentro no importan nada de los de afuera.
- Ejemplo
La regla «una factura de más de 10k necesita aprobación» es una clase común, sin imports del framework web ni del ORM.
- Coste
- Más capas y más mapeo de datos entre ellas.
- Cuándo usarlo
- Productos de larga vida con reglas complejas.
- Relaciones
Gemela de Hexagonal; suele vivir dentro de los módulos de un Modular Monolith.
Los frameworks son detalles. Tratalos como el empapelado, no como los cimientos.
A cierta escala — de carga o de cantidad de equipos — una sola aplicación deja de alcanzar. Estos patrones cortan el sistema en piezas independientes y, a cambio, te entregan una red con todas sus fallas.
Microservices — microservicios
Un patio de comidas: cada local tiene su cocina, su menú y su caja. Si se llena la pizzería, ponen dos cocineros más; el de ensaladas no lo necesita.
El sistema se parte en servicios (services) chicos: cada uno es dueño de una capacidad de negocio y de su propia base de datos, y se despliega y escala por separado. Los servicios hablan por la red — HTTP o un bus de mensajes.
- Problema
Muchos equipos se pisan en el mismo código; las partes del sistema tienen cargas muy desparejas.
- Idea
- Servicios separados, con bases separadas y despliegue separado.
- Ejemplo
Servicios
orders,inventory,delivery; en Black Friday escalás solo pedidos y pagos.- Coste
Sistema distribuido: latencia de red, sin transacciones simples entre servicios, operación y debugging complicados.
- Cuándo usarlo
Equipos grandes y carga despareja. Para una startup de cinco personas es exagerado.
- Relaciones
Crece desde Modular Monolith; se comunica por Event-driven y Queues; para operaciones compartidas hace falta Saga.
Serverless — funciones a demanda
En lugar de tener un auto parado sin uso, llamás un taxi y pagás solo mientras corre el taxímetro.
Escribís funciones (functions) chicas, y la nube las corre cuando llega un evento, las escala sola de cero a miles de copias y de vuelta, y te cobra por cada ejecución.
- Problema
El servidor está ocioso y cuesta plata, mientras la carga llega a picos.
- Idea
- El código corre solo ante un evento; del escalado se encarga la nube.
- Ejemplo
Subís una imagen al storage → una función genera el thumbnail → entre subidas no corre nada.
- Coste
Cold start (demora de la primera ejecución), límites de tiempo, atadura a la nube.
- Cuándo usarlo
Trabajo a picos y con forma de evento: procesar archivos, webhooks, tareas programadas.
- Relaciones
- Se lleva naturalmente con Event-driven.
Los sistemas distribuidos convierten llamadas a funciones en llamadas de red. Y cada una de ellas puede fallar.
Apenas tenés más de una pieza, la arquitectura está sobre todo en las líneas entre ellas. Cómo hablan decide cómo fallan.
Request–Response — preguntá y esperá
Pedir en un mostrador: preguntás, te quedás parado, recibís tu café — y recién ahí seguís.
El cliente manda una request y espera la response. Es comunicación síncrona: REST, gRPC, una query a la base de datos.
- Problema
- Necesitás la respuesta ya mismo para seguir.
- Idea
- Llamás → esperás → seguís.
- Ejemplo
- El checkout llama a la API de pagos y espera la confirmación.
- Coste
Acoplamiento en el tiempo: si el servidor está lento o caído, el que llama también queda trabado.
- Cuándo usarlo
Por defecto — cuando la respuesta de verdad hace falta enseguida.
- Relaciones
- Lo opuesto a los asíncronos Event-driven y Queues.
Event-driven Architecture — anunciá y que los oyentes reaccionen
Una redacción: sale una noticia y deportes, clima y avisos reaccionan solos. El que anuncia no los espera y ni siquiera sabe quién escucha.
Un componente no llama a los demás: publica un evento (event) — un hecho que ya pasó: «OrderPlaced». Al que le interesa, está suscrito y reacciona. Dos variantes: broker (los eventos circulan libremente) y mediator (un coordinador corre los pasos en orden).
- Problema
Un servicio tiene que conocer y llamar a todos a los que les importa que algo pasó.
- Idea
Publicá el hecho; los suscriptores reaccionan solos y de forma independiente.
- Ejemplo
«OrderPlaced» → email al cliente, reserva en inventario, registro en analytics.
- Coste
El flujo es difícil de seguir y de testear; los eventos llegan duplicados o fuera de orden.
- Cuándo usarlo
Muchas reacciones independientes a una misma acción; efectos secundarios lentos.
- Relaciones
Funciona sobre Queues / Pub-Sub; base de Event Sourcing y Saga.
Message Queue y Pub/Sub — un correo entre las piezas
El correo guarda la carta hasta que el destinatario esté listo. La dejás en el buzón y te vas; la lee cuando se despierta.
Una cola de mensajes (message queue) o un broker pub/sub se pone entre emisor y receptor para que no tengan que estar online al mismo tiempo. En una cola, cada mensaje lo toma un solo worker; en pub/sub, cada mensaje les llega a todos los suscriptores.
- Problema
El trabajo lento demora la respuesta al usuario; los picos de carga tiran abajo el sistema.
- Idea
- Dejar la tarea en una cola y procesarla después, a su propio ritmo.
- Ejemplo
Un reporte pesado va a una cola (RabbitMQ, Kafka, SQS), un worker lo hace en segundo plano y el sitio sigue rápido.
- Coste
El resultado llega diferido; hay que pensar en reintentos y mensajes duplicados.
- Cuándo usarlo
Tareas en segundo plano, suavizar picos, comunicación entre servicios.
- Relaciones
- Transporte para Event-driven y Microservices.
Pipe-and-Filter — una línea de montaje para datos
Una línea de embotellado: lavar, llenar, tapar, etiquetar. Cada estación hace una cosa y pasa la botella.
Los datos fluyen por una cadena de pasos independientes — filtros (filters) unidos por tuberías (pipes). Cada filtro hace una sola transformación.
- Problema
Un procesamiento de datos complejo se vuelve una única función gigante.
- Idea
- Partirlo en pasos simples, cada uno con su entrada y su salida.
- Ejemplo
grep | sort | uniq, un job de ETL, un compilador (tokenizar → parsear → optimizar → generar).- Coste
Encaja mal cuando los pasos necesitan volver atrás o ponerse de acuerdo.
- Cuándo usarlo
- El trabajo es una secuencia clara de transformaciones.
- Relaciones
- Los pasos se suelen unir con Queues.
Síncrono es una llamada telefónica. Asíncrono es una carta.
Estos patrones no son sobre cajas, sino sobre cómo escribís, leés y guardás la verdad.
CQRS — modelos separados para escribir y leer
Una biblioteca tiene un catálogo rápido para buscar y una trastienda donde los libros se acomodan en los estantes. Buscar está optimizado para una cosa; guardar, para otra.
CQRS (Command Query Responsibility Segregation) separa el modelo de escritura — los comandos (commands) que cambian los datos — del modelo de lectura — las queries que los traen. Cada uno se puede optimizar y escalar por separado.
- Problema
Un mismo modelo de datos sirve mal tanto para escrituras complejas como para lecturas rápidas.
- Idea
Dos modelos: escritura — con todas las reglas; lectura — «vistas» precalculadas.
- Ejemplo
Un dashboard lee de una vista desnormalizada; los pedidos se escriben en una base transaccional.
- Coste
Hay que sincronizar dos modelos; la lectura puede quedar un poco atrasada (eventual consistency).
- Cuándo usarlo
Hay muchas más lecturas que escrituras, o tienen formas muy distintas. No por defecto.
- Relaciones
Suele ir en pareja con Event Sourcing: los eventos del log construyen el modelo de lectura.
Event Sourcing — guardá la historia, no el estado
Un banco no guarda solo tu saldo, sino cada depósito y cada extracción. El saldo es solo la suma. Si lo perdés, lo recalculás desde el libro mayor.
En lugar de sobrescribir el estado actual, guardás un flujo de eventos (event log), agregando siempre al final. El estado actual se obtiene reproduciendo (replay) los eventos.
- Problema
Necesitás saber no solo «qué hay ahora», sino también «cómo se llegó a eso».
- Idea
La fuente de verdad es el log de eventos; el estado se calcula a partir de él.
- Ejemplo
Una cuenta: «abierta, +100, −30, +5» en vez de «saldo: 75» — auditoría completa y respuesta a «¿cómo estaba el martes pasado?».
- Coste
Consultar «qué hay ahora» es más difícil; los eventos no se pueden editar — la historia es para siempre.
- Cuándo usarlo
- Finanzas, auditoría, procesos de negocio complejos.
- Relaciones
Casi siempre con CQRS; combina naturalmente con Event-driven.
Saga — una operación larga que podés deshacer
Reservás un viaje: vuelo, hotel, auto. Si se cae el auto, cancelás el hotel y el vuelo. No hay un único botón «deshacer todo»; vas desandando paso a paso.
Cuando una acción de negocio pasa por varios servicios, cada uno con su base de datos, no se puede hacer una sola transacción común. Una Saga es una cadena de transacciones locales; si un paso falla, se corren acciones compensatorias (compensations) que deshacen los pasos anteriores.
- Problema
- Una operación toca varios servicios y no hay una transacción común.
- Idea
Pasos uno tras otro, cada uno con un paso «de deshacer» por si algo falla.
- Ejemplo
Crear pedido → reservar stock → cobrar la tarjeta; si falla el cobro, liberar el stock y cancelar el pedido.
- Coste
Cada paso necesita su compensación; entre pasos, los datos quedan inconsistentes por un rato.
- Cuándo usarlo
- Operaciones de negocio que cruzan Microservices.
- Relaciones
Necesita Microservices; los pasos se suelen coordinar con Event-driven.
Una transacción es un átomo de intención. Cuando abarca varios servicios, el átomo lo tenés que construir vos.
Estos patrones existen para un dolor específico. Echá mano de ellos cuando tengas exactamente ese dolor — y ni un segundo antes.
Microkernel — un núcleo chico y plug-ins
Un taladro: un solo motor y una docena de puntas. El taladro es el mismo; cambiás la punta según el trabajo.
Un núcleo (core) mínimo da la base, y todo lo demás llega como plug-ins que se enchufan al núcleo y no dependen unos de otros.
- Problema
Hay muchas funciones, cambian seguido y son distintas para cada cliente.
- Idea
- Un núcleo chico y estable + plug-ins independientes.
- Ejemplo
VS Code y los navegadores con extensiones; un sistema de seguros donde las reglas de cada región son un plug-in.
- Coste
- Hay que diseñar con cuidado la API de plug-ins y su compatibilidad.
- Cuándo usarlo
- Productos plataforma, personalización por cliente.
- Relaciones
Los plug-ins se suelen enchufar por puertos, como en Hexagonal.
Space-based Architecture — datos en memoria, sin cuello de botella
Un estadio con veinte boleterías, cada una con su propia copia del mapa de butacas — en lugar de una sola taquilla con una fila enorme.
Cuando una única base de datos se vuelve el cuello de botella bajo una carga enorme, el trabajo se reparte entre muchas processing units, cada una con los datos en memoria. La memoria se sincroniza entre ellas (data grid), y los datos se escriben en la base más tarde, de forma asíncrona.
- Problema
- Una sola base de datos no aguanta la carga concurrente en los picos.
- Idea
Datos en la memoria de muchos nodos, sincronizados entre sí, y escritura en la base — después.
- Ejemplo
Una venta flash o un remate online con una marea de pujas simultáneas.
- Coste
- Muy complejo y caro; riesgo de perder datos entre la memoria y la base.
- Cuándo usarlo
- Solo con una carga concurrente realmente enorme y a picos.
- Relaciones
- Usa caché y escritura asíncrona, como Queues.
Peer-to-Peer — sin centro
Una comida a la canasta: cada uno es a la vez cocinero e invitado. Sin restaurante, sin mozo — el grupo se alimenta solo.
Los nodos — peers — hablan directamente entre sí, sin servidor central. Cada uno es a la vez cliente y servidor.
- Problema
- Un servidor central es un punto de falla caro y vulnerable.
- Idea
- Los participantes se reparten la carga y los datos entre ellos.
- Ejemplo
BitTorrent: todo el que descarga también sube — cuanta más gente, más fuerte la red.
- Coste
- Es difícil asegurar consistencia, seguridad y control.
- Cuándo usarlo
Distribución de archivos, blockchain, resiliencia sin un host central.
- Relaciones
Lo opuesto a las formas cliente-servidor como Request–Response.
Los patrones exóticos son medicina, no vitaminas. Tomalos para un diagnóstico confirmado.
Los patrones son un vocabulario, no un menú del que pedís un solo plato. Los sistemas reales combinan varios, y la jugada más sabia suele ser la más simple.
Los patrones están relacionados entre sí
Una casa usa a la vez muros de carga, plomería y cableado — no «el único patrón de construcción verdadero».
Los patrones no viven solos. El monolith modular crece hacia microservicios; los microservicios necesitan eventos, colas y sagas; Hexagonal y Clean son la misma idea; CQRS y Event Sourcing andan en pareja.
Un sistema real puede ser un monolith modular por fuera, Clean Architecture en cada módulo, Request–Response para la interfaz, eventos para los efectos secundarios lentos y una cola delante del job pesado. La pregunta no es «qué patrón» sino «qué patrones, y dónde».
Empezá con la forma más simple
No colás los cimientos de un estadio para construir una cabaña.
Casi todo sistema debería empezar como Modular Monolith y ganarse su complejidad. Microservices, CQRS, Event Sourcing, Space-based — son respuestas a problemas de escala y de tamaño de equipo que quizás nunca tengas. El sistema distribuido más barato es el que no construiste.
- ¿Qué problema recurrente resuelve esta forma? Nombralo en una sola frase.
- ¿Tengo ese problema ahora — o estoy adivinando sobre el futuro?
- ¿Cuánto cuesta? En latencia, operación, complejidad, plata.
- ¿Cuál es el patrón más simple que igual funcionaría? Empezá por ahí.
- ¿Puedo adoptarlo más adelante, cuando el dolor realmente aparezca?
- Hay más servicios que ingenieros.
- Una sola acción de usuario toca cinco servicios y dos colas.
- CQRS o Event Sourcing llegaron antes que el problema de lectura o de auditoría.
- Nadie en el equipo puede dibujar el sistema de memoria.
- Elegiste el patrón porque es lo que hacen las empresas grandes.
Resumen: los 17 patrones
Estructurar una aplicación
- Layereden capas, n-tier
Código en pisos: presentación → lógica → datos → base. La request baja de arriba hacia abajo.
- Modular Monolithmonolith modular
Una sola aplicación, partida en módulos con interfaces claras. El mejor default.
- MVC / MVVMModel–View–Controller
Una pared entre la interfaz y los datos con sus reglas.
Dirección de las dependencias
- HexagonalPorts and Adapters
El núcleo declara puertos; las tecnologías se enchufan con adaptadores.
- Clean / Onionlimpia / cebolla
Círculos; todas las dependencias apuntan al centro (dependency rule).
Partir en piezas
- Microservicesmicroservicios
Servicios separados con su base y su despliegue. El precio: un sistema distribuido.
- ServerlessFaaS
Funciones por evento; la nube escala, pagás por ejecución.
Cómo hablan las piezas
- Request–Responsellamada síncrona
Preguntás y esperás la respuesta. Simple, pero acopla en el tiempo.
- Event-drivenorientada a eventos
Publicás un hecho; los suscriptores reaccionan solos.
- Message Queue / Pub-Subcola de mensajes
La tarea espera en la cola hasta que un worker se libere.
- Pipe-and-Filterlínea de montaje
Los datos pasan por una cadena de pasos simples.
Datos
- CQRSCommand Query Responsibility Segregation
Modelos separados para escribir y para leer.
- Event Sourcingalmacenamiento basado en eventos
Guardás el log de eventos; el estado es su replay.
- Sagasaga
Pasos a través de varios servicios + compensaciones si algo falla.
Formas especiales
- Microkernelarquitectura de plug-ins
Un núcleo chico y plug-ins independientes.
- Space-baseddata grid en memoria
Datos en la memoria de muchos nodos; la base deja de ser el cuello de botella.
- Peer-to-PeerP2P
Los nodos hablan directamente, sin centro.
La mejor arquitectura es la más simple que sobrevive a tus requisitos reales — y ni un patrón más.