Planteamiento y contexto
Operas GET /catalog detrás de una CDN y una caché de aplicación. El origen puede ser lento durante los despliegues, pero los clientes prefieren un catálogo ligeramente desactualizado antes que una página en blanco. Diseña los encabezados de caché y la ruta de revalidación mientras mantienes los datos de los inquilinos (tenants) aislados y la frescura medible.
Asume que las respuestas del catálogo son públicas por inquilino, las escrituras pasan por el origen y un cambio de precio de emergencia debe hacerse visible rápidamente. La respuesta debe distinguir entre una alternativa de disponibilidad y el permiso para servir estado sensible.
Qué evalúa el entrevistador
- Si comprendes la frescura, la obsolescencia, la revalidación y la política separada de
stale-if-error. - Si las claves de caché varían según el inquilino, la autorización, la configuración regional (locale) y la negociación de contenido.
- Si los fallos de caché (misses) concurrentes desencadenan una sola solicitud al origen o un efecto manada (thundering herd).
- Si un operador puede revocar la entrega de datos obsoletos y demostrar la frescura mediante métricas.
Preguntas para aclarar antes de responder
- ¿La respuesta es pública, a nivel de inquilino o específica de un usuario? Los datos privados no deben ser compartidos en absoluto por una CDN.
- ¿Cuál es la antigüedad máxima tolerada para lecturas normales y para una caída del origen? Estas se convierten en ventanas separadas de frescura y obsolescencia.
- ¿Puede un cambio de precio o de permisos invalidar el objeto de inmediato? De ser así, añade purgas o claves versionadas en lugar de confiar únicamente en el TTL.
- ¿Se dispone de validadores?
ETagoLast-Modifiedtransforman una recuperación completa en una revalidación condicional.
Estructura de respuesta en 30 segundos
“Defino una ventana de frescura, una ventana acotada de stale-while-revalidate y una ventana separada de stale-if-error. La clave de caché incluye cada límite de representación y autorización; los datos específicos del usuario son privados. Un acierto obsoleto (stale hit) responde rápidamente y desencadena una única solicitud condicional en segundo plano, mientras que los fallos concurrentes se coalescen. Los cambios de emergencia purgan o versionan la clave. Las métricas exponen la antigüedad, los resultados de la revalidación, el uso de stale-if-error y pruebas de filtración entre inquilinos, y un operador puede desactivar la entrega de datos obsoletos”.
Análisis paso a paso a fondo
1. Separar la frescura de la disponibilidad
max-age define durante cuánto tiempo es fresca una respuesta almacenada. stale-while-revalidate permite que una caché entregue una respuesta obsoleta durante un intervalo acotado mientras revalida en segundo plano. stale-if-error es un margen de disponibilidad independiente ante un error del origen. Ninguna de las directivas hace que los datos obsoletos sean correctos, y una respuesta con must-revalidate o una regla aplicable de no-cache no puede reutilizarse a la ligera.
Un catálogo público podría utilizar una ventana de frescura corta y una ventana de obsolescencia acotada más larga. Un endpoint de permisos, un saldo de cuenta o un precio de emergencia deberían utilizar private, no-store, una ruta de purga o una política mucho más estricta. El riesgo del negocio determina la ventana, no el valor por defecto de la caché.
2. Construir una clave de caché segura y un contrato de respuesta
La clave debe incluir el inquilino, la configuración regional, la codificación y cualquier encabezado de solicitud nombrado por Vary. Nunca permitas que una respuesta autenticada entre en una caché compartida a menos que la representación sea explícitamente pública e independiente de la autorización. Una respuesta puede declarar su política claramente:
Cache-Control: public, max-age=30, stale-while-revalidate=120, stale-if-error=600
Vary: Accept-Encoding, Accept-Language, X-Tenant-ID
ETag: "catalog-tenant-7-v42"El servidor debe validar que X-Tenant-ID se derive de la ruta o el host autenticado, no de un valor arbitrario del cliente. Si un límite de inquilino no puede representarse de forma segura en la clave, desactiva la caché compartida.
3. Revalidar sin efecto manada
Ante un acierto obsoleto, entrega el cuerpo almacenado y encola una sola revalidación por clave de caché. Utiliza un bloqueo corto o un mapa de single-flight para que diez mil lectores no generen diez mil llamadas al origen. El revalidador envía If-None-Match; un 304 Not Modified renueva la frescura sin reemplazar el cuerpo, mientras que un nuevo 200 reemplaza el objeto y el validador.
Si la revalidación falla con un error transitorio, conserva el objeto antiguo únicamente dentro del límite de stale-if-error. Registra el fallo y la antigüedad. No extiendas la ventana de obsolescencia indefinidamente reiniciando su temporizador de forma repetida.
4. Hacer explícita la invalidación
El TTL es una red de seguridad, no un control de emergencia. Un cambio de precio o de permisos debe publicar un evento de invalidación versionado o purgar las claves afectadas. La ruta de escritura puede confirmar la nueva versión antes de publicar el evento; los consumidores deben ser idempotentes y permitir reintentos. Si la purga no puede confirmarse, la API puede asociar un período corto de must-revalidate o eludir la caché para el inquilino afectado.
5. Medir y operar la política
Monitorea la antigüedad de la respuesta, la tasa de aciertos frescos, la tasa de aciertos de stale-while-revalidate, el recuento de stale-if-error, la latencia de revalidación, la tasa de 304, la tasa de errores de origen, la contención de bloqueos y la cardinalidad de claves de caché. Genera alertas cuando la antigüedad de los datos obsoletos se aproxime al máximo, ante picos inesperados de stale-if-error y fallos en las pruebas entre inquilinos.
Proporciona un feature flag o un interruptor de emergencia a nivel de ruta para detener la entrega de respuestas obsoletas. Prueba fallos en frío, aciertos obsoletos concurrentes, tiempos de espera agotados (timeouts) del origen, cambios de validador, condiciones de carrera en purgas, encabezados de inquilinos, variantes regionales y una actualización de precios de emergencia. El oráculo de la prueba es el contrato de frescura y aislamiento, no solo un número de latencia más bajo.
Ejemplo de respuesta de alta calidad
Comenzaría clasificando los datos. Un catálogo público a nivel de inquilino puede tener max-age=30, stale-while-revalidate=120 y un stale-if-error=600 justificado por separado; los datos específicos de usuario o de permisos deben ser privados o no almacenarse en caché. La clave incluye dimensiones de inquilino y de representación, y la respuesta lleva un validador.
Ante un acierto obsoleto, entrego el cuerpo y ejecuto una sola revalidación condicional por clave. 304 renueva la frescura y 200 reemplaza el objeto. Una falla transitoria del origen puede utilizar la ventana acotada de stale-if-error, nunca un temporizador reiniciado infinitamente. Las escrituras publican eventos de purga o versión idempotentes para cambios urgentes. Monitoreo la antigüedad, el uso de datos obsoletos, los resultados de la revalidación y el aislamiento de inquilinos, con un interruptor de emergencia para la entrega de datos obsoletos.
Errores comunes
- Error: Aplicar
stale-while-revalidatea datos de cuenta o de permisos → Por qué falla: una respuesta obsoleta rápida puede exponer una decisión de autorización inválida → Solución: mantener los datos sensibles como privados o no almacenados en caché. - Error: Omitir el inquilino o la configuración regional de la clave → Por qué falla: una representación puede servirse a otro límite → Solución: derivar y probar cada dimensión de la clave.
- Error: Renovar el temporizador de obsolescencia tras cada revalidación fallida → Por qué falla: los datos de una caída pueden persistir para siempre → Solución: aplicar un límite absoluto de tiempo para datos obsoletos.
- Error: Enviar una solicitud al origen por cada lector que recibe datos obsoletos → Por qué falla: una ráfaga de lecturas obsoletas se convierte en un efecto manada → Solución: utilizar revalidación single-flight por clave.
- Error: Tratar el TTL como una invalidación de emergencia → Por qué falla: los cambios urgentes esperan a la expiración → Solución: publicar eventos de purga o versión y verificar su finalización.
Preguntas de seguimiento y respuestas
¿Por qué no usar únicamente stale-if-error?
Solo ayuda cuando la solicitud al origen encuentra un error. stale-while-revalidate mejora la latencia habitual sirviendo una respuesta antigua mientras se ejecuta una actualización exitosa. Resuelven condiciones distintas y necesitan límites y métricas independientes.
¿Qué ocurre cuando el validador cambia durante una purga?
Versiona el objeto y haz que el evento de purga sea idempotente. Una revalidación que ve el validador antiguo no debe sobrescribir una versión más reciente; compara las versiones del objeto o las marcas de tiempo de confirmación antes de reemplazar la entrada en caché. Si el orden es incierto, elude la caché brevemente para esa clave.
¿Puede una CDN almacenar en caché una respuesta autenticada con Vary: Authorization?
Técnicamente es posible en algunos sistemas, pero es un diseño de alto riesgo. Es preferible private o una representación pública explícita para el inquilino. Si una caché compartida es inevitable, demuestra la clave, la independencia de autorización, la purga y el aislamiento entre inquilinos mediante pruebas de integración y controles operativos.