🏗️

Diseño de Sistemas

👨‍🍳 Chef

El arte de diseñar sistemas que escalan

Imagina que eres el arquitecto de un restaurante. No solo decides donde van las mesas, sino como fluye la cocina, cuantos cocineros necesitas, donde almacenas los ingredientes, y que pasa cuando llegan 500 clientes en vez de 50.

El diseño de sistemas es exactamente eso: planificar como construir software que funcione bien hoy y pueda crecer mañana.

Un buen diseño de sistema no es el mas complejo, sino el que resuelve el problema actual con espacio para crecer.


Monolito vs Microservicios

La primera decision arquitectonica que enfrentaras.

Monolito: Todo en uno

┌─────────────────────────────────────┐
│           APLICACION                │
│  ┌─────┐ ┌─────┐ ┌─────┐ ┌─────┐   │
│  │Auth │ │Users│ │Orders│ │Pay  │   │
│  └─────┘ └─────┘ └─────┘ └─────┘   │
│         Una base de datos           │
│              ┌───┐                  │
│              │ DB│                  │
│              └───┘                  │
└─────────────────────────────────────┘

Ventajas:

  • Simple de desarrollar y desplegar
  • Facil de debuggear (todo en un lugar)
  • Una sola base de datos = consistencia
  • Ideal para equipos pequenos (<10 devs)

Desventajas:

  • Escala todo o nada
  • Un bug puede tumbar todo
  • Deployments arriesgados
  • Dificil de mantener cuando crece

Microservicios: Divide y conquista

┌─────────┐  ┌─────────┐  ┌─────────┐
│  Auth   │  │  Users  │  │ Orders  │
│ Service │  │ Service │  │ Service │
└────┬────┘  └────┬────┘  └────┬────┘
     │            │            │
┌────┴────┐  ┌────┴────┐  ┌────┴────┐
│Auth DB  │  │Users DB │  │Orders DB│
└─────────┘  └─────────┘  └─────────┘

Ventajas:

  • Escala solo lo que necesitas
  • Equipos independientes
  • Falla un servicio, no todo
  • Tecnologias diferentes por servicio

Desventajas:

  • Complejidad operacional alta
  • Debugging distribuido es dificil
  • Consistencia eventual (no inmediata)
  • Requiere DevOps maduros

Cuando usar cada uno

EscenarioRecomendacion
Startup, MVP, < 5 devsMonolito
Producto probado, > 20 devsMicroservicios
Partes con cargas muy diferentesHibrido
No sabes cual elegirMonolito

Regla de oro: Empieza con monolito. Extrae microservicios cuando el dolor sea real, no imaginado.


El Teorema CAP

En sistemas distribuidos, solo puedes tener 2 de 3:

        Consistency
           /\
          /  \
         /    \
        /      \
       /   ??   \
      /          \
     /____________\
Availability    Partition
                Tolerance
  • Consistency (C): Todos ven los mismos datos al mismo tiempo
  • Availability (A): El sistema siempre responde
  • Partition Tolerance (P): Funciona aunque haya fallas de red

En la practica

Las particiones de red SIEMPRE pueden ocurrir. Entonces realmente eliges entre:

SistemaEligeSacrificaEjemplo
CPConsistenciaDisponibilidadBancos, inventarios
APDisponibilidadConsistenciaRedes sociales, cache

Ejemplo real: En un banco, si hay falla de red, prefieres que el cajero diga "No disponible" (CP) a que te deje retirar dinero que no tienes (AP).


Escalamiento: Vertical vs Horizontal

Vertical: Maquina mas grande

Antes:          Despues:
┌─────┐         ┌─────────┐
│ 4GB │   →     │  64GB   │
│ 2CPU│         │  32CPU  │
└─────┘         └─────────┘
  • Simple: solo cambias el servidor
  • Tiene limite fisico
  • Un solo punto de falla

Horizontal: Mas maquinas

Antes:          Despues:
┌─────┐         ┌─────┐ ┌─────┐ ┌─────┐
│ 4GB │   →     │ 4GB │ │ 4GB │ │ 4GB │
└─────┘         └─────┘ └─────┘ └─────┘
  • Teoricamente infinito
  • Requiere Load Balancer
  • Tu app debe ser stateless

Load Balancers

Distribuyen trafico entre multiples servidores.

                    ┌─────────┐
                    │  Load   │
        Usuarios →  │Balancer │
                    └────┬────┘
                         │
           ┌─────────────┼─────────────┐
           ▼             ▼             ▼
      ┌─────────┐   ┌─────────┐   ┌─────────┐
      │Server 1 │   │Server 2 │   │Server 3 │
      └─────────┘   └─────────┘   └─────────┘

Algoritmos de distribucion

AlgoritmoComo funcionaCuando usarlo
Round Robin1, 2, 3, 1, 2, 3...Servidores iguales
Least ConnectionsAl que tenga menosConexiones largas
IP HashMismo cliente → mismo serverSesiones sticky
WeightedMas al mas potenteServidores diferentes

Escalando Bases de Datos

Replicacion: Copias de lectura

     Writes
        │
        ▼
   ┌─────────┐
   │ Primary │──────────────┐
   │  (RW)   │              │ Replicacion
   └─────────┘              │
        │                   │
        ▼                   ▼
   ┌─────────┐         ┌─────────┐
   │ Replica │         │ Replica │
   │  (RO)   │         │  (RO)   │
   └─────────┘         └─────────┘
        ▲                   ▲
        │                   │
      Reads              Reads
  • Escala lecturas, no escrituras
  • Consistencia eventual (retraso de replicacion)

Sharding: Divide los datos

user_id 1-1000      user_id 1001-2000    user_id 2001-3000
       │                   │                    │
       ▼                   ▼                    ▼
  ┌─────────┐         ┌─────────┐         ┌─────────┐
  │ Shard 1 │         │ Shard 2 │         │ Shard 3 │
  └─────────┘         └─────────┘         └─────────┘
  • Escala tanto lecturas como escrituras
  • Complejidad: JOINs entre shards son costosos
  • Elegir buena shard key es critico

Caching: La clave del performance

Estrategias de cache

Cache-Aside (Lazy Loading)

1. App pide dato
2. Cache miss? → Lee de DB → Guarda en cache
3. Cache hit? → Retorna de cache

┌─────┐  miss   ┌─────┐        ┌────┐
│ App │ ──────→ │Cache│        │ DB │
│     │ ←────── │     │        │    │
└─────┘  hit    └─────┘        └────┘
    │                              ▲
    └──────────────────────────────┘
         miss: lee y guarda

Write-Through

Escribe en cache Y en DB al mismo tiempo
- Datos siempre consistentes
- Escrituras mas lentas

Write-Behind (Write-Back)

Escribe en cache, luego async a DB
- Escrituras rapidas
- Riesgo de perder datos si cache falla

Que cachear

CandidatoPrioridad
Datos que no cambian (config)Alta
Datos leidos frecuentementeAlta
Resultados de calculos costososAlta
Datos de usuario activoMedia
Datos que cambian cada segundoBaja

Message Queues

Para comunicacion asincrona entre servicios.

┌─────────┐     ┌─────────────┐     ┌─────────────┐
│Producer │ ──→ │    Queue    │ ──→ │  Consumer   │
│ (API)   │     │ (RabbitMQ)  │     │  (Worker)   │
└─────────┘     └─────────────┘     └─────────────┘

Casos de uso

  • Envio de emails: API encola, worker envia
  • Procesamiento de imagenes: Upload encola, worker procesa
  • Notificaciones: Evento encola, multiples consumers notifican

Herramientas populares

ToolMejor para
RabbitMQMensajeria tradicional, routing complejo
Redis StreamsSimple, ya tienes Redis
KafkaAlto volumen, event sourcing
SQSAWS nativo, simple

Caso practico: Disenando un URL Shortener

Requisitos

Funcionales:

  • Acortar URL larga → codigo corto
  • Redirigir codigo → URL original
  • URLs expiran (opcional)

No funcionales:

  • 100M URLs nuevas/mes
  • 10:1 ratio lectura:escritura
  • Latencia < 100ms

Estimaciones

URLs/mes: 100M
URLs/seg: 100M / (30 * 24 * 3600) ≈ 40 URLs/seg escritura
Lecturas: 40 * 10 = 400 URLs/seg lectura

Storage (5 años):
100M * 12 * 5 = 6B URLs
6B * 500 bytes = 3TB

Diseno del codigo corto

Base62: [a-zA-Z0-9] = 62 caracteres

7 caracteres = 62^7 = 3.5 trillones de combinaciones
Suficiente para 100M/mes por siglos

Arquitectura final

                    ┌───────────┐
     Usuarios  ───→ │    LB     │
                    └─────┬─────┘
                          │
              ┌───────────┴───────────┐
              ▼                       ▼
         ┌─────────┐             ┌─────────┐
         │ API 1   │             │ API 2   │
         └────┬────┘             └────┬────┘
              │                       │
              └───────────┬───────────┘
                          │
                    ┌─────┴─────┐
                    │   Redis   │ (Cache hot URLs)
                    └─────┬─────┘
                          │
                    ┌─────┴─────┐
                    │ Postgres  │ (Sharded by hash)
                    └───────────┘

Recursos recomendados


Practica

-> Workshop de Arquitectura - Disena un sistema real paso a paso