Marco para Entrevistas de Diseño de Sistemas
Las entrevistas de diseño de sistemas evalúan tu capacidad para diseñar sistemas a gran escala bajo ambigüedad. A diferencia de las entrevistas de código con respuestas correctas claras, las entrevistas de diseño de sistemas evalúan tu capacidad para hacer compensaciones razonables, comunicarte claramente y demostrar amplitud de conocimiento. Esta guía proporciona un marco estructurado que funciona para cualquier pregunta de diseño de sistemas.
Lo Que Buscan los Entrevistadores
- Comunicación: ¿Puedes articular tu pensamiento claramente?
- Enfoque de resolución de problemas: ¿Trabajas metódicamente o saltas a soluciones?
- Análisis de compensaciones: ¿Puedes evaluar diferentes opciones y justificar tus elecciones?
- Profundidad técnica: ¿Entiendes las tecnologías que propones usar?
- Conciencia de escalabilidad: ¿Puedes identificar y abordar cuellos de botella?
- Experiencia práctica: ¿Tu diseño refleja consideraciones del mundo real?
Paso 1: Clarificar Requisitos (5 minutos)
Este es el paso más importante. Muchos candidatos fallan porque diseñan el sistema equivocado. Haz preguntas para entender el alcance, restricciones y prioridades.
Requisitos Funcionales
¿Qué necesita hacer el sistema? Sé específico sobre funcionalidades principales vs. deseables.
// Example: "Design a URL shortener"
// Questions to ask:
// - Should users be able to customize short URLs?
// - Do short URLs expire?
// - Do we need analytics (click counts, geographic data)?
// - Is there authentication or can anyone create URLs?
interface FunctionalRequirements {
core: string[];
secondary: string[];
outOfScope: string[];
}
const urlShortenerRequirements: FunctionalRequirements = {
core: [
"Create short URL from long URL",
"Redirect short URL to original URL",
"Short URLs should be unique and non-guessable",
],
secondary: [
"Custom aliases",
"URL expiration",
"Click analytics",
],
outOfScope: [
"User authentication",
"Rate limiting UI",
"Admin dashboard",
],
};Requisitos No Funcionales
Estos impulsan tus decisiones de arquitectura más que los requisitos funcionales.
interface NonFunctionalRequirements {
scale: {
dailyActiveUsers: number;
readWriteRatio: number;
peakMultiplier: number;
};
performance: {
readLatency: string;
writeLatency: string;
};
availability: string;
consistency: string;
durability: string;
}
// Key questions:
// - How many users? DAU/MAU?
// - What is the read/write ratio?
// - What are the latency requirements?
// - What consistency level is needed?
// - What are the availability requirements?Paso 2: Estimación Rápida (3-5 minutos)
Cálculos rápidos para validar la dirección de tu diseño. Enfócate en los números que influyen las decisiones de arquitectura.
// Example: URL shortener estimation
// Given: 100M URLs created per month
const urlsPerMonth = 100_000_000;
const writeQPS = urlsPerMonth / (30 * 24 * 3600); // ~40 writes/sec
// Read QPS (assuming 100:1 read:write ratio)
const readQPS = writeQPS * 100; // ~4,000 reads/sec
const peakReadQPS = readQPS * 3; // ~12,000 reads/sec at peak
// Storage (5-year horizon)
const urlsIn5Years = urlsPerMonth * 12 * 5; // 6 billion URLs
const avgRecordSize = 500; // bytes
const totalStorage = urlsIn5Years * avgRecordSize; // 3 TB
// Conclusions:
// - QPS is manageable with a single database + caching
// - 3 TB fits on a single machine but sharding is reasonable
// - Caching hot URLs in Redis will handle most readsPaso 3: Diseño de Alto Nivel (10 minutos)
Dibuja los componentes principales y sus interacciones. Comienza simple y agrega complejidad según sea necesario.
// High-level components for URL shortener
//
// Client -> Load Balancer -> API Servers -> Database
// -> Cache (Redis)
const architectureDecisions = {
loadBalancer: "AWS ALB - distributes traffic, SSL termination",
apiServers: "Node.js - handles HTTP, stateless, horizontally scalable",
database: "PostgreSQL - reliable, handles 40 writes/sec easily",
cache: "Redis - in-memory, sub-ms reads for hot URLs",
idGeneration: "Base62 encoding of auto-increment ID or pre-generated IDs",
};Paso 4: Diseño Detallado (15 minutos)
Profundiza en 2-3 componentes que son más interesantes o desafiantes. El entrevistador puede guiarte a áreas específicas.
// Deep dive: Short URL generation strategy
// Option 1: Hash-based (MD5/SHA256 + truncate)
function hashBased(longUrl: string): string {
const hash = md5(longUrl);
return base62Encode(hash.substring(0, 7));
// Problem: collisions possible
}
// Option 2: Counter-based (auto-increment + base62)
function counterBased(counter: bigint): string {
return base62Encode(counter);
// Problem: predictable, sequential
}
// Option 3: Pre-generated key service
class KeyGenerationService {
private localKeys: string[] = [];
async getKey(): Promise<string> {
if (this.localKeys.length === 0) {
this.localKeys = await this.fetchKeyBatch(1000);
}
return this.localKeys.pop()!;
}
}
// Decision: Option 3 because:
// - No collision handling needed
// - Keys are not sequential (better security)
// - Scales well (batch fetching reduces DB calls)Paso 5: Cuellos de Botella y Compensaciones (5 minutos)
Identifica proactivamente debilidades en tu diseño y propón mitigaciones. Esto demuestra pensamiento de ingeniería maduro.
| Cuello de Botella | Impacto | Mitigación |
|---|---|---|
| Base de datos única | Límite de rendimiento de escritura, punto único de fallo | Agregar réplicas de lectura, particionar por hash de código corto |
| Desalojo de caché | Caché frío causa sobrecarga de base de datos | Calentar caché al iniciar, usar desalojo LRU |
| Claves populares | URLs virales sobrecargan un solo nodo de caché | Replicar claves populares en múltiples nodos de caché |
| Abuso / spam | Usuarios maliciosos crean millones de URLs | Rate limiting por IP/usuario, CAPTCHA para no autenticados |
Errores Comunes a Evitar
- Saltar a la solución. Gastar 30 segundos en requisitos y 35 minutos en diseño es al revés. Los requisitos impulsan todo
- Sobreingeniería. Usar Kafka, Kubernetes y microservicios para un sistema que sirve 100 usuarios. Comienza simple, escala cuando sea necesario
- No hacer estimaciones. Sin números, no puedes justificar si necesitas un solo servidor o 100
- Monologar. La entrevista es una conversación, no una presentación. Verifica con el entrevistador regularmente
- Ignorar compensaciones. Cada decisión de diseño tiene pros y contras. Declara explícitamente
- No conocer tus herramientas. Si propones usar Cassandra, deberías saber cuándo es mejor o peor que PostgreSQL
- Enfocarte en los detalles equivocados. Gastar 10 minutos en el esquema de base de datos cuando el entrevistador quiere discutir estrategia de caché
- Olvidar los fallos. ¿Qué pasa cuando un servidor falla? ¿Cuando la base de datos está caída? ¿Cuando la red se particiona?
Consejos de Entrevistadores
- Conduce la conversación. Los mejores candidatos lideran la discusión mientras se mantienen abiertos al feedback
- Piensa en voz alta. Los entrevistadores no pueden evaluar lo que no pueden escuchar. Comparte tu razonamiento, incluso cuando no estés seguro
- Sé honesto sobre lo que no sabes. Decir "no estoy seguro de cómo exactamente Kafka maneja esto, pero creo que..." es mejor que inventar algo
- Usa números reales y tecnologías reales. "Usaremos PostgreSQL con unas 10,000 escrituras/seg estimadas" es mejor que "Usaremos una base de datos"
- Atiende las pistas del entrevistador. Si preguntan "¿qué hay de los escenarios de fallo?", dedica tiempo a ese tema
Hoja de Ruta de Práctica
Construye tus habilidades de diseño de sistemas progresivamente:
| Semana | Área de Enfoque | Problemas de Práctica |
|---|---|---|
| 1-2 | Fundamentos | Acortador de URL, paste bin, almacén clave-valor |
| 3-4 | Sistemas intensivos en datos | Feed de Twitter, feed de noticias, sistema de notificaciones |
| 5-6 | Sistemas en tiempo real | Aplicación de chat, streaming en vivo, edición colaborativa |
| 7-8 | Sistemas complejos | Viajes compartidos, sistema de pagos, motor de búsqueda |
| 9-10 | Entrevistas simuladas | Practicar con pares, sesiones cronometradas, ciclos de feedback |