Codea Seguro Codea Seguro
Arquitectura de Software Nivel: basic Arquitectura Software

Ejercicio entrevista: entender la caché (nivel inicial)

Ejercicio práctico muy básico para entender qué es una caché, cuándo usarla y cómo funciona un HIT y un MISS.

Un ejercicio de entrada para entender qué es una caché antes de meternos en diseños más grandes. Es el ladrillo que después reutilizamos en casi todos los sistemas que escalan.

Planteo del problema

Tenemos una página que muestra la ficha de un producto (nombre, precio, foto). Esa página se visita miles de veces por minuto, y cada visita hace la misma consulta a la base de datos:

SELECT nombre, precio, foto FROM productos WHERE id = 42;

El problema: el producto casi no cambia, pero igual le pegamos a la base de datos en cada visita. La base se sobrecarga y la página empieza a ir lenta.

¿Cómo harías para que la página responda más rápido y la base de datos trabaje menos?

La idea: una caché

Una caché es un lugar donde guardamos temporalmente una respuesta que pedimos seguido, para no tener que volver a calcularla o buscarla desde cero.

Analogía: en vez de ir a la biblioteca (la base de datos) cada vez que necesitás un dato, dejás el libro más usado sobre tu escritorio (la caché). Está al lado tuyo y lo consultás al instante.

La caché suele vivir en memoria (por ejemplo Redis), que es muchísimo más rápida que consultar la base de datos.

Cómo funciona: HIT y MISS

Cuando llega una visita, la aplicación pregunta primero a la caché:

  • HIT (acierto): el dato está en la caché → lo devolvemos al instante, sin tocar la base de datos.
  • MISS (fallo): el dato no está → vamos a la base de datos, devolvemos la respuesta y de paso la guardamos en la caché para la próxima vez.
flowchart LR
    user["Usuario"] --> app["Aplicación"]
    app -->|"1. ¿está en caché?"| cache[("Caché")]
    cache -->|"HIT: la devuelve"| app
    cache -.->|"MISS"| db[("Base de datos")]
    db -.->|"la guarda en caché"| cache

    style cache fill:#9dcc4d,stroke:#4d6c20,color:#0f172a

En código, el patrón (llamado read-through) se ve así:

async function getProducto(id) {
  // 1. Miramos la caché primero
  const cacheado = await cache.get(`producto:${id}`);
  if (cacheado) return cacheado; // HIT → listo

  // 2. MISS: vamos a la base de datos
  const producto = await db.getProducto(id);

  // 3. Guardamos en caché para las próximas visitas (5 minutos)
  await cache.set(`producto:${id}`, producto, { ttl: 300 });

  return producto;
}

La primera visita es un MISS (paga la consulta a la base); las miles siguientes son HIT y ni la tocan.

El detalle importante: los datos pueden quedar viejos

Si guardamos el producto en la caché y alguien cambia el precio, la caché seguiría devolviendo el precio viejo hasta que se actualice. A eso se le dice dato stale (desactualizado).

TIP

La forma más simple de manejarlo es un TTL (time to live): le decimos a la caché “guardá esto por 5 minutos”. Pasado ese tiempo se borra solo y la próxima visita vuelve a leer de la base de datos. Es un buen equilibrio entre velocidad y frescura.

CAUTION

No todo sirve para cachear. Datos que cambian a cada segundo o que deben ser siempre exactos (por ejemplo, el saldo de una cuenta) no son buenos candidatos: ahí el dato viejo puede causar errores.

Qué evaluamos en el candidato

  • Que entienda por qué la caché ayuda: evita repetir trabajo caro (la consulta a la base).
  • Que sepa explicar HIT y MISS con sus palabras.
  • Que mencione que los datos pueden quedar desactualizados y una forma de manejarlo (TTL).
  • Bonus: que note que la caché es útil sobre todo cuando se lee mucho más de lo que se escribe.