El caché es una de esas cosas que puede hacer que una web se sienta mucho más rápida… o puede regalarte tres horas de confusión porque “yo cambié eso y todavía se ve igual”.
Bien usado, evita repetir trabajo innecesario. Mal usado, sirve contenido viejo, esconde errores y convierte un problema simple en un misterio con olor a producción.
La idea no es cachear todo por moda. La idea es entender qué se puede guardar, por cuánto tiempo, dónde conviene guardarlo y qué nunca deberías cachear sin pensarlo dos veces.
Qué es caché
Caché es guardar una respuesta, archivo o resultado para reutilizarlo después sin tener que calcularlo, descargarlo o pedirlo otra vez.
Ejemplo simple:
Primera visita:
Usuario → servidor → aplicación → base de datos → respuesta
Siguiente visita con caché:
Usuario → caché → respuesta
La diferencia parece pequeña, pero en tráfico real puede ser enorme. Si 10,000 usuarios piden el mismo logo, el mismo CSS o la misma página pública, no tiene sentido hacer que todo pase por la aplicación y la base de datos cada vez.
El caché reduce:
- tiempo de respuesta;
- consumo de CPU;
- consultas a base de datos;
- ancho de banda;
- costo de infraestructura;
- carga sobre servidores de origen.
Pero también introduce una pregunta incómoda: ¿cuándo deja de ser válida esa copia guardada?
Ahí empieza lo interesante.
Dónde puede existir caché
En una web moderna, el caché puede vivir en varios lugares.
Navegador → CDN → servidor web → aplicación → base de datos
Cada capa puede guardar cosas distintas.
1. Caché del navegador
El navegador puede guardar imágenes, CSS, JavaScript, fuentes y algunas respuestas. Así, cuando el usuario vuelve a entrar, no descarga todo desde cero.
Esto se controla principalmente con headers HTTP:
Cache-Control: public, max-age=31536000, immutable
Eso le dice al navegador: “puedes guardar esto por bastante tiempo; no va a cambiar”.
Es ideal para archivos versionados como:
/app.a8f3c1.js
/styles.91bd2.css
/logo.webp
Si el archivo tiene hash o versión en el nombre, puedes cachearlo agresivamente. Cuando cambie, generas otro nombre y listo.
2. Caché en CDN
Un CDN como Cloudflare, Fastly, Akamai o CloudFront guarda contenido cerca del usuario. En vez de que cada visita viaje hasta tu servidor, muchas respuestas salen desde un nodo cercano.
Esto ayuda mucho con:
- imágenes;
- CSS y JavaScript;
- archivos descargables;
- páginas públicas con poco cambio;
- APIs públicas repetitivas;
- tráfico internacional.
Ejemplo práctico: si tu servidor está en Virginia y alguien entra desde Santo Domingo, un CDN puede entregar imágenes o assets desde un punto más cercano, reduciendo latencia y carga en el origen.
Pero un CDN no arregla todo. Si tu aplicación genera una respuesta personalizada para cada usuario, el CDN no debería servirle esa misma respuesta a todo el mundo. Ahí es donde empiezan los sustos.
3. Caché en el servidor web
Nginx y Apache pueden cachear o controlar caché sin que la aplicación se entere demasiado.
Esto es útil para servir rápido archivos estáticos, comprimir respuestas y evitar que todo pase por el backend.
Ejemplo típico en Nginx para assets:
location ~* \.(css|js|jpg|jpeg|png|webp|svg|ico|woff2?)$ {
expires 30d;
add_header Cache-Control "public, max-age=2592000, immutable";
access_log off;
}
En Apache, una idea parecida sería:
<IfModule mod_expires.c>
ExpiresActive On
ExpiresByType text/css "access plus 30 days"
ExpiresByType application/javascript "access plus 30 days"
ExpiresByType image/webp "access plus 30 days"
ExpiresByType image/png "access plus 30 days"
</IfModule>
<IfModule mod_headers.c>
<FilesMatch "\.(css|js|png|jpg|jpeg|webp|svg|ico|woff2?)$">
Header set Cache-Control "public, max-age=2592000, immutable"
</FilesMatch>
</IfModule>
La idea no es copiar y pegar esto a ciegas. La idea es entender el patrón: archivos estáticos y versionados pueden vivir más tiempo en caché.
4. Caché en la aplicación
La aplicación también puede guardar resultados costosos.
Por ejemplo:
- lista de categorías;
- menú público;
- configuración del sitio;
- resultados de una consulta pesada;
- respuesta de una API externa;
- HTML generado para una página pública.
Ejemplo conceptual:
const key = `product:${productId}`;
let product = await cache.get(key);
if (!product) {
product = await database.products.findById(productId);
await cache.set(key, product, { ttl: 300 }); // 5 minutos
}
return product;
Eso evita consultar la base de datos en cada request si el dato puede vivir cinco minutos sin problema.
El punto clave es el TTL: time to live. Cuánto tiempo esa información puede considerarse suficientemente válida.
Cuándo sí usar caché
El caché tiene mucho sentido cuando algo cumple estas condiciones:
- se lee muchas veces;
- cambia poco;
- cuesta calcularlo o descargarlo;
- no es peligroso si vive un tiempo guardado;
- puede invalidarse cuando cambia.
Buenos candidatos:
Assets estáticos → CSS, JS, imágenes, fuentes
Páginas públicas → home, blog, landing pages
Datos de catálogo → categorías, marcas, filtros
APIs repetidas → tasas, catálogos, configuraciones públicas
Consultas pesadas → reportes que no cambian cada segundo
Ejemplo realista: un blog no necesita generar la misma página desde cero para cada visita. Si el post cambia una vez al día o una vez a la semana, cachearlo es sentido común.
Lo mismo pasa con imágenes. Si una imagen pesa 300 KB y la piden miles de usuarios, cachearla en navegador y CDN es casi obligatorio.
Cuándo no usar caché, o usarlo con mucho cuidado
No todo debe cachearse.
Hay rutas y datos donde una respuesta vieja puede causar problemas serios:
/login
/logout
/admin
/checkout
/cart
/payment
/api/me
/api/session
/api/orders
/api/user/profile
/api/permissions
/api/inventory/reserve
En general, cuidado con:
- datos privados de usuario;
- sesiones;
- permisos;
- carritos de compra;
- pagos;
- balances;
- inventario crítico;
- respuestas con cookies;
- contenido que cambia por usuario;
- endpoints administrativos;
- APIs donde cada respuesta depende del estado actual.
Un error clásico: cachear una página que parece pública, pero incluye datos del usuario logueado en una esquina.
Hola, Carlos
Si eso se cachea como respuesta pública, puedes terminar mostrándole el nombre de un usuario a otro. Bonito para una auditoría. Horrible para dormir tranquilo.
Para rutas privadas o sensibles, normalmente quieres algo como:
Cache-Control: no-store
no-store significa: no guardes esta respuesta. Ni navegador, ni proxy, ni CDN deberían conservarla.
Para contenido que puede revalidarse pero no reutilizarse libremente, también existen combinaciones como:
Cache-Control: private, no-cache
private indica que solo el navegador del usuario puede guardar la respuesta, no un CDN compartido. no-cache no significa “no guardar nunca”; significa “puedes guardarlo, pero debes revalidar antes de usarlo”. Nombre confuso, porque HTTP decidió ser HTTP.
Código, CDN o servidor web: dónde conviene cachear
No hay una sola respuesta. Depende de qué estás cacheando.
Cachear en código
Úsalo cuando la aplicación entiende mejor la lógica del dato.
Ejemplos:
- resultado de una consulta;
- permisos calculados internamente;
- configuraciones;
- respuestas de APIs externas;
- fragmentos de HTML;
- objetos de negocio.
Ventaja: tienes control fino.
Desventaja: tienes que diseñar invalidación, TTL, claves y consistencia.
Si cambias un producto, ¿cómo borras product:123 del caché? Si cambias una categoría, ¿qué páginas dependen de ella? Esa parte no se resuelve con esperanza.
Cachear en CDN
Úsalo cuando la respuesta es pública y repetida.
Ejemplos:
- imágenes;
- assets estáticos;
- páginas públicas;
- descargas;
- contenido global;
- respuestas API que no dependen de cookies o sesión.
Ventaja: reduces latencia y descargas trabajo del servidor de origen.
Desventaja: si cacheas demasiado amplio, puedes servir contenido viejo o privado.
Regla práctica: si una respuesta depende de Cookie, Authorization o del usuario actual, no la trates como pública.
Cachear en Nginx o Apache
Úsalo para controlar headers, servir estáticos rápido o agregar una capa simple delante de la aplicación.
Ejemplos:
- assets versionados;
- archivos públicos;
- respuestas de backend bajo reglas claras;
- microcaché de páginas anónimas con mucho tráfico.
Nginx, por ejemplo, también puede hacer fastcgi_cache o proxy_cache, pero ahí hay que ser más cuidadoso. Ya no solo estás diciendo “guarda imágenes”; estás guardando respuestas dinámicas.
Ejemplo conceptual de bypass para rutas sensibles:
location ~ ^/(login|logout|admin|checkout|cart) {
add_header Cache-Control "no-store" always;
proxy_pass http://app;
}
Y para assets:
location /assets/ {
add_header Cache-Control "public, max-age=31536000, immutable" always;
try_files $uri =404;
}
Una buena configuración separa claramente lo público de lo privado.
Rutas que normalmente no deben estar cacheadas
Aunque cada aplicación tiene su realidad, estas rutas suelen ser mala idea para caché compartido:
Autenticación:
/login
/logout
/register
/forgot-password
/reset-password
Usuario:
/account
/profile
/settings
/api/me
/api/session
Administración:
/admin
/dashboard
/wp-admin
Ecommerce:
/cart
/checkout
/payment
/orders
/api/orders
/api/inventory
Webhooks y callbacks:
/webhook
/callback
/oauth/callback
/api/payment/confirm
También cuidado con cualquier ruta que:
- use tokens temporales;
- cambie según permisos;
- devuelva información personal;
- modifique estado;
- dependa de cookies;
- responda distinto por usuario;
- tenga datos legales, financieros o médicos.
Para esas rutas, mejor explícito:
Cache-Control: no-store
Y si usas CDN, crea reglas de bypass para ellas.
Rutas que sí suelen beneficiarse
Buenos candidatos para caché:
/
/about
/blog
/posts/*
/assets/*
/images/*
/css/*
/js/*
/fonts/*
robots.txt
sitemap.xml
Pero incluso ahí hay matices. El home de una tienda puede parecer público, pero si muestra precios personalizados, ubicación del usuario o inventario exacto por zona, ya no es tan simple.
La pregunta correcta no es “¿puedo cachear esta ruta?”. La pregunta es:
Si esta respuesta se reutiliza por X minutos, ¿qué puede salir mal?
Si la respuesta es “nada grave”, cachea. Si la respuesta es “un usuario ve datos de otro”, no te hagas el creativo.
Headers importantes
Los headers son la forma en que el servidor le habla al navegador, CDN y proxies sobre caché.
Cache-Control
El más importante.
Cache-Control: public, max-age=3600
Significa que puede guardarse por una hora.
Cache-Control: public, max-age=31536000, immutable
Bueno para archivos versionados que no cambian.
Cache-Control: no-store
No guardar. Útil para datos sensibles.
Cache-Control: private, max-age=300
El navegador del usuario puede guardar, pero no un caché compartido como CDN.
ETag
Permite revalidar si el contenido cambió.
ETag: "abc123"
El navegador puede preguntar: “¿sigue siendo esta versión?”. Si sí, el servidor responde 304 Not Modified y evita reenviar todo.
Last-Modified
Parecido a ETag, pero basado en fecha.
Last-Modified: Mon, 29 Jun 2026 12:00:00 GMT
No siempre es perfecto, pero ayuda para archivos estáticos.
Cómo revisar si algo está cacheado
Puedes mirar headers con curl:
curl -I https://example.com/app.css
Busca cosas como:
cache-control: public, max-age=31536000, immutable
etag: "..."
cf-cache-status: HIT
age: 245
Si usas Cloudflare, cf-cache-status puede darte pistas:
HIT → salió del caché
MISS → no estaba en caché
BYPASS → una regla lo saltó
EXPIRED → estaba, pero venció
DYNAMIC → no se cacheó como estático
También puedes probar dos veces:
curl -o /dev/null -s -w 'Total: %{time_total}s\n' https://example.com/
curl -o /dev/null -s -w 'Total: %{time_total}s\n' https://example.com/
Si la segunda respuesta mejora mucho, puede haber caché en alguna capa. No es prueba absoluta, pero es una señal.
En DevTools, el panel Network también muestra si algo vino de disk cache, memory cache o desde red.
Errores comunes
1. Cachear antes de medir
Si no sabes qué está lento, puedes cachear lo incorrecto.
Primero mide:
- TTFB;
- peso total;
- número de requests;
- consultas lentas;
- CPU/memoria;
- headers;
- tiempos de CDN.
Cachear sin medir es como ponerle música alta al carro para no oír el ruido del motor.
2. No tener estrategia de invalidación
El caché necesita una forma de actualizarse cuando el contenido cambia.
Opciones comunes:
- TTL corto;
- purga manual;
- purga automática al publicar;
- versionado de archivos;
- claves por entidad (
product:123); - eventos que invalidan datos relacionados.
Sin invalidación, tarde o temprano alguien dirá: “pero en mi computadora todavía sale viejo”. Y sí, sale viejo porque tú le dijiste que lo guardara.
3. Cachear respuestas con cookies
Si una respuesta cambia según la cookie del usuario, cuidado. Muchas plataformas y CDNs evitan cachear automáticamente cuando ven cookies, pero no confíes a ciegas.
El problema no es solo rendimiento. Es privacidad.
4. Usar TTL eterno en archivos sin versión
Esto está bien:
/assets/app.9f31ab.js
Esto es más peligroso:
/assets/app.js
Si cacheas app.js por un año y luego lo cambias sin cambiar el nombre, muchos usuarios seguirán usando la versión vieja.
Por eso los builds modernos generan nombres con hash.
5. Creer que caché arregla una mala arquitectura
El caché puede reducir presión, pero no corrige todo.
Si una consulta no tiene índice, si una API externa tarda 8 segundos, si el frontend pesa 12 MB o si el servidor está mal configurado, el caché puede ayudar en algunos casos, pero también puede ocultar el problema.
Primero entiende la causa. Luego decide si cachear.
Una regla práctica
Antes de cachear algo, hazte estas preguntas:
- ¿Esto se pide muchas veces?
- ¿Cambia poco?
- ¿Es costoso generarlo o descargarlo?
- ¿Es público o privado?
- ¿Qué pasa si alguien ve una versión vieja?
- ¿Cómo lo invalido cuando cambie?
- ¿Dónde conviene cachearlo: navegador, CDN, servidor o aplicación?
Si no puedes responder esas preguntas, todavía no tienes estrategia. Tienes fe. Y la fe no es un plan de caching.
Idea final
El caché no es un botón mágico de rendimiento. Es una decisión de arquitectura.
Usado bien, hace que una web responda más rápido, soporte más tráfico y gaste menos recursos. Usado mal, entrega datos viejos, rompe sesiones, oculta bugs y puede exponer información privada.
Cachea lo público, repetido y estable. Evita cachear lo privado, sensible o demasiado cambiante. Usa headers claros. Versiona archivos. Define TTL. Ten una forma de invalidar.
La web rápida no es la que cachea todo. Es la que sabe exactamente qué puede dejar de repetir.