Daniel Murillo
Índice

Arquitectura · 24 de octubre de 2026 · Daniel Murillo

Caché y compresión: optimizar antes de escalar

La caché evita trabajo repetido; la compresión reduce bytes. Cómo aplicarlas con seguridad en REST, GraphQL, gRPC y tiempo real.

La caché evita trabajo repetido; la compresión reduce los datos que se transmiten. Son estrategias complementarias, pero cada una tiene costes y límites.

Introducción

Cuando una API es lenta, la primera reacción puede ser cambiar de protocolo, aumentar la infraestructura o dividir el backend en más servicios. Sin embargo, una parte importante del rendimiento puede mejorar al reutilizar resultados, reducir bytes innecesarios y entregar los recursos de manera adecuada.

Este artículo explora caché y compresión como estrategias transversales que pueden beneficiar APIs REST, GraphQL, gRPC y aplicaciones con comunicación en tiempo real, aunque no se configuren igual en todas ellas.

1. Caché: no repetir el trabajo

Una caché almacena un resultado para reutilizarlo después. Puede reducir consultas a la base de datos, procesamiento y transferencia.

Capas frecuentes:

  • Caché local del cliente.
  • Caché HTTP del navegador.
  • CDN o proxy.
  • Caché de aplicación, por ejemplo Redis.
  • Cachés internas del motor de base de datos.

Cada capa tiene una finalidad diferente. No basta con activar una caché: hay que definir qué se almacena, cuánto tiempo, quién puede reutilizarlo y cómo se invalida.

2. Caché HTTP

Para una respuesta cacheable, el servidor puede enviar:

Cache-Control: public, max-age=60
ETag: "product-123-v4"
Vary: Accept-Encoding

Cache-Control define políticas de almacenamiento. ETag identifica una versión del recurso y permite validación condicional. Vary indica que ciertos encabezados de la solicitud afectan a la representación seleccionada.

Con If-None-Match, el cliente puede preguntar si el recurso cambió. Si no cambió, el servidor responde 304 Not Modified y evita retransmitir el cuerpo.

Las respuestas privadas o personalizadas necesitan políticas adecuadas. Nunca debe compartirse en una CDN una respuesta de usuario si la configuración no garantiza que la caché esté aislada correctamente.

3. Caché de aplicación

Redis o una caché en memoria pueden almacenar resultados de operaciones costosas. Son útiles cuando múltiples solicitudes reutilizan datos y el coste de calcularlos de nuevo es elevado.

Sin embargo, también introducen problemas:

  • Invalidación de datos.
  • Expiración y frescura.
  • Claves mal diseñadas.
  • Consumo de memoria.
  • Inconsistencias entre instancias.
  • Efectos de una caché fría.

La caché debe responder a una necesidad observada. Cachear indiscriminadamente puede agregar complejidad sin reducir el coste real.

4. Gzip, Brotli y Zstandard

La compresión reduce el tamaño del contenido transmitido, pero consume CPU para comprimir y descomprimir.

Gzip

Es ampliamente compatible y funciona bien con JSON, HTML, CSS y JavaScript. Para respuestas dinámicas, un nivel intermedio como 5 o 6 suele ser un punto de partida razonable, pero debe medirse.

Brotli

Puede producir archivos textuales más pequeños que Gzip en muchos escenarios. Es especialmente útil para recursos web estáticos y puede servir para respuestas dinámicas si la infraestructura lo soporta. Los niveles altos pueden costar más CPU.

Zstandard

Ofrece niveles y un equilibrio entre velocidad y compresión que puede resultar útil en servicios internos y procesamiento de datos. El soporte para compresión HTTP debe verificarse en todos los componentes; no debe asumirse que cada navegador y proxy lo soporta.

5. Elegir la compresión por carga de trabajo

No existe un nivel universalmente óptimo.

  • Respuestas pequeñas: el ahorro puede ser insignificante y no compensar el coste de compresión.
  • Respuestas medianas: Gzip moderado suele ser un punto de partida práctico.
  • Respuestas grandes y textuales: Brotli o Gzip pueden reducir notablemente la transferencia.
  • CPU saturada: una compresión agresiva puede aumentar la latencia.
  • Red lenta o costosa: ahorrar bytes puede aportar más valor.
  • Contenido ya comprimido: volver a comprimir JPEG, WebP, AVIF, vídeo o audio normalmente aporta poco.

Mide tamaño original, tamaño comprimido, tiempo de compresión, tiempo de descompresión y CPU bajo carga.

6. Archivos estáticos frente a respuestas dinámicas

Los archivos estáticos se generan durante el build y suelen mantenerse iguales hasta una nueva publicación. Por eso pueden precomprimirse:

assets/
├── app.js
├── app.js.gz
└── app.js.br

El servidor o CDN selecciona la variante compatible con Accept-Encoding. Así, no se necesita comprimir el archivo en cada solicitud.

Los recursos versionados por contenido pueden tener una política larga:

Cache-Control: public, max-age=31536000, immutable

Esto solo es adecuado si el nombre cambia cuando cambia el contenido.

Las respuestas dinámicas, en cambio, pueden depender del usuario, los permisos y los datos actuales. Comprimirlas en cada solicitud consume CPU y debe configurarse con umbrales y niveles adecuados.

7. ¿Cómo encaja en cada modelo de comunicación?

REST: puede aprovechar caché HTTP de forma natural para recursos y operaciones compatibles, además de compresión de respuestas.

GraphQL: puede utilizar caché de entidades, resultados, consultas persistidas y caché HTTP en operaciones compatibles. La forma de la consulta y las variables influyen en la identidad del resultado.

gRPC: puede reutilizar resultados en la aplicación y comprimir mensajes cuando esté soportado y resulte beneficioso. La caché HTTP convencional no se aplica automáticamente como a un GET REST.

WebSockets y SSE: la estrategia suele centrarse en estado de aplicación, snapshots, eventos y recuperación tras reconexiones. La compresión depende del transporte y de las extensiones negociadas.

8. Compresión y seguridad

La compresión de datos sensibles junto con información controlada por un atacante puede crear riesgos en determinados contextos, especialmente cuando los tamaños comprimidos revelan información. Hay que evaluar el diseño de seguridad, no activar compresión indiscriminadamente.

También conviene evitar dobles compresiones en proxies y CDN, y configurar correctamente la negociación de contenido.

9. Un proceso de optimización práctico

  1. Medir el tamaño y la frecuencia de las respuestas.
  2. Identificar datos repetidos y operaciones costosas.
  3. Definir qué respuestas pueden almacenarse de forma segura.
  4. Establecer expiración e invalidación.
  5. Separar archivos estáticos de respuestas dinámicas.
  6. Precomprimir recursos estáticos.
  7. Probar Gzip y Brotli con tamaños representativos.
  8. Medir CPU, latencia y bytes transferidos.
  9. Validar comportamiento con concurrencia real.
  10. Revisar la consistencia y seguridad de las cachés.

Conclusión

La caché y la compresión atacan problemas distintos. La primera evita trabajo repetido; la segunda reduce los bytes transmitidos. Combinadas correctamente, pueden mejorar el rendimiento sin cambiar el protocolo de comunicación.

Pero ninguna debe aplicarse a ciegas. Una caché incorrecta puede entregar datos obsoletos o privados; una compresión excesiva puede consumir CPU y aumentar la latencia.

Optimiza lo que realmente cuesta: reutiliza resultados cuando sea seguro y comprime cuando el ahorro de transferencia compense el procesamiento adicional.

En esta serie

  1. REST: cómo diseñar y optimizar una API
  2. REST vs GraphQL
  3. gRPC vs REST
  4. WebSockets, SSE y Webhooks
  5. Caché y compresión (esta nota)
  6. Benchmarks y decisiones de arquitectura

Referencias