ETag: qué es, mecanismo de almacenamiento en caché y configuración del encabezado

Autor: IT Sectr Publicado: 2026-03-09 Tiempo de lectura: 8 min

ETag (Entity Tag) es un encabezado HTTP que asigna un identificador único a una versión de un recurso en el servidor, permitiendo al cliente verificar eficientemente la vigencia de los datos almacenados en caché. En una solicitud repetida, el navegador o la aplicación envía el ETag guardado, y el servidor lo compara con el actual: si coinciden, devuelve un estado 304 Not Modified sin cuerpo de respuesta. Según RFC 7232 (IETF, 2014), las solicitudes condicionales con ETag reducen el volumen de datos transferidos hasta en un 95% para recursos solicitados con frecuencia. Esto hace que el encabezado sea críticamente importante para el rendimiento de las aplicaciones móviles.

Puntos clave

  • ETag — un encabezado HTTP con un identificador único de versión de recurso para solicitudes condicionales y almacenamiento en caché
  • Cómo funciona — el servidor genera un hash del contenido o un número de versión, el cliente lo envía en el encabezado If-None-Match
  • ETags fuertes y débiles — fuertes (el contenido es idéntico byte a byte) y débiles (el contenido es semánticamente equivalente, prefijo W/)
  • 304 Not Modified — respuesta del servidor cuando el ETag coincide, ahorrando tráfico y acelerando la carga
  • ETag vs Last-Modified — ETag es más preciso (hash del contenido), Last-Modified es más simple (fecha), juntos brindan la máxima eficiencia

¿Qué es ETag?

ETag (Entity Tag) es un encabezado de respuesta HTTP que contiene un identificador único para una versión específica de un recurso. El servidor calcula el ETag basándose en el contenido del archivo, sus metadatos o número de revisión y lo envía al cliente en la respuesta a una solicitud GET. El cliente guarda este identificador y en solicitudes posteriores al mismo recurso lo envía en el encabezado If-None-Match. Si el recurso no ha cambiado, el servidor responde con 304 Not Modified y el cliente usa su copia almacenada en caché.

El formato de ETag se define en RFC 7232 como una cadena entre comillas: "33a64df551425fcc55e4d42a148795d9f25f89d4". El valor puede ser un hash SHA-1 del contenido del archivo, un número de versión incremental, una combinación de inode-número-tiempo para archivos estáticos o un token arbitrario generado por el servidor. El único requisito es que el valor debe cambiar cuando el recurso cambie y no debe cambiar si el recurso permanece igual.

ETag pertenece a los mecanismos de solicitudes condicionales (conditional requests), una de las optimizaciones básicas del protocolo HTTP. A diferencia de las solicitudes incondicionales, donde el servidor siempre devuelve una respuesta completa, una solicitud condicional permite al cliente verificar la vigencia de la caché sin recargar los datos. Según HTTP Archive (2025), alrededor del 40% de todas las respuestas HTTP son 304 Not Modified gracias a una configuración adecuada de ETag y Last-Modified.

Dónde se aplica ETag

ETag se utiliza en APIs REST para optimizar la carga de colecciones de datos: si la lista de objetos no ha cambiado, el cliente recibe 304 sin transferir todo el JSON. En archivos estáticos (CSS, JS, imágenes), ETag permite a las CDN y navegadores verificar eficientemente la vigencia de la caché. En aplicaciones móviles, ETag es crítico para la sincronización en segundo plano: la aplicación verifica si los datos en el servidor han cambiado y descarga actualizaciones solo cuando es necesario. Esto ahorra tráfico y batería del dispositivo.

¿Cómo funciona ETag?

El ciclo completo de ETag consta de cuatro pasos. El servidor genera un ETag en la primera solicitud y lo devuelve en el encabezado de respuesta. El cliente guarda el ETag junto con el recurso en caché. En una solicitud repetida, el cliente envía el encabezado If-None-Match con el valor del ETag guardado. El servidor compara el valor recibido con el ETag actual del recurso: si coinciden, devuelve 304 Not Modified con cuerpo vacío; si no coinciden, devuelve 200 OK con el nuevo recurso y un nuevo ETag.

http
// Solicitud del cliente con If-None-Match
GET /api/users HTTP/1.1
Host: example.com
If-None-Match: "33a64df551425fcc55e4d42a148795d9f25f89d4"

// Respuesta del servidor — el recurso no ha cambiado
HTTP/1.1 304 Not Modified
ETag: "33a64df551425fcc55e4d42a148795d9f25f89d4"

En una aplicación móvil, este ciclo se puede implementar mediante un cliente HTTP con soporte de caché. OkHttp, por ejemplo, gestiona automáticamente ETag a través de CacheInterceptor: guarda el ETag de la respuesta y agrega If-None-Match en solicitudes repetidas. Al recibir 304, OkHttp devuelve los datos en caché. OkHttp soporta ETag sin configuración adicional: solo hay que habilitar la caché mediante OkHttpClient.Builder.cache().

Generación de ETag en el servidor

El servidor puede calcular ETags de diferentes maneras: mediante un hash MD5 o SHA del contenido, mediante un número de revisión de la base de datos (por ejemplo, updated_at de MySQL), mediante una combinación de inode + mtime + tamaño para archivos estáticos (Nginx genera ETags exactamente de esta manera). Para APIs dinámicas, el hash del contenido es el más confiable: si la respuesta JSON cambia aunque sea un campo, el ETag cambiará. Sin embargo, calcular un hash en cada solicitud carga la CPU; para sistemas de alta carga, es mejor usar un número de versión incremental.

ETags fuertes y débiles

RFC 7232 define dos tipos de ETags: fuertes (strong) y débiles (weak). Un ETag fuerte significa que dos representaciones del recurso son idénticas byte a byte, ni un solo bit difiere. Un ETag débil (prefijo W/) garantiza solo equivalencia semántica: el contenido puede diferir a nivel de serialización (espacios, orden de campos JSON), pero los datos se consideran iguales para el cliente. Los ETags débiles se marcan con el prefijo W/, por ejemplo W/"1a2b3c".

La elección del tipo de ETag depende de los requisitos de precisión de la comparación. Para archivos estáticos (CSS, JS, imágenes), son preferibles los ETags fuertes: si el archivo ha cambiado, el cliente debe obtener la nueva versión. Para APIs dinámicas, donde el mismo JSON puede serializarse con diferente orden de campos o formato, los ETags débiles brindan más flexibilidad: el servidor genera el ETag basándose en los datos de negocio, no en la representación en cadena.

Tipo de ETagFormatoGarantíaAplicación
Strong (fuerte)"hash"Identidad byte a byteArchivos estáticos, recursos binarios
Weak (débil)W/"hash"Equivalencia semánticaAPI JSON, páginas dinámicas

Una limitación de los ETags débiles: no pueden usarse con solicitudes de rango (Range requests). Si el cliente solicita una parte de un archivo, el servidor debe devolver un ETag fuerte para garantizar que el fragmento corresponde al recurso completo. Los ETags débiles no ofrecen esa garantía. En otros escenarios, los ETags débiles son seguros y recomendados para APIs.

ETag vs Last-Modified

ETag y Last-Modified son dos encabezados HTTP para solicitudes condicionales que a menudo se usan juntos. Last-Modified indica la fecha de la última modificación de un recurso y funciona con el encabezado If-Modified-Since. ETag proporciona un identificador único de versión y funciona con If-None-Match. Cada uno tiene sus ventajas y limitaciones, y combinarlos brinda la máxima eficiencia de almacenamiento en caché.

Last-Modified es más simple de implementar: el servidor obtiene automáticamente la fecha del sistema de archivos o actualiza el campo updated_at en la base de datos. Sin embargo, la fecha tiene precisión de segundos, lo que es insuficiente para recursos que cambian varias veces por segundo. Además, Last-Modified no distingue entre diferentes estados: si un archivo se sobrescribe con la misma versión, la fecha cambia pero el contenido no, por lo que el cliente recargará datos idénticos.

ETag es más preciso: cambia solo cuando el contenido cambia realmente. Si el servidor restaura una versión anterior desde una copia de seguridad, el ETag cambia. Si un archivo se sobrescribe con los mismos datos, el ETag permanece igual y el cliente no recarga. El uso combinado es recomendado por la especificación HTTP: el servidor devuelve ambos encabezados, el cliente envía If-None-Match e If-Modified-Since simultáneamente. Si al menos un encabezado indica un cambio, el servidor devuelve un nuevo recurso.

Prioridad de los encabezados

Según la especificación, ETag tiene prioridad sobre Last-Modified. Si el servidor recibe If-None-Match, debe verificar solo el ETag, ignorando If-Modified-Since. Esto evita condiciones de carrera: si el recurso cambió entre el momento en que el cliente envió Last-Modified y la verificación en el servidor, ETag será el indicador más actualizado. En la práctica, los servidores suelen verificar ambos encabezados, pero cuando los resultados no coinciden, ETag gana.

Implementación de ETag en el servidor

La configuración de ETag depende del tipo de servidor. Nginx genera ETags para archivos estáticos automáticamente basándose en inode, mtime y tamaño. Apache usa el mecanismo FileETag. Para aplicaciones dinámicas en Node.js, PHP, Python, Ruby, los ETags deben generarse programáticamente: mediante un hash de la respuesta, un número de versión de datos o una combinación de parámetros de solicitud.

go
func etagMiddleware(next http.Handler) http.Handler {
    return http.HandlerFunc(func(w http.ResponseWriter,
        r *http.Request) {
        // Generar ETag basado en datos
        etag := generateETag(r.URL.Path)
        w.Header().Set("ETag", etag)

        // Verificar If-None-Match
        if r.Header.Get("If-None-Match") == etag {
            w.WriteHeader(http.StatusNotModified)
            return
        }
        next.ServeHTTP(w, r)
    })
}

Un middleware en Go intercepta la solicitud, genera un ETag para la URL solicitada (por ejemplo, calcula un hash de datos de la caché o la base de datos) y establece el encabezado de respuesta. Si el cliente envió If-None-Match y coincide con el ETag actual, el servidor devuelve 304 Not Modified inmediatamente, sin llamar al controlador principal. En producción, conviene agregar almacenamiento en caché de los ETags calculados por URL y parámetros para reducir la carga del servidor.

Problemas y dificultades

En una configuración de múltiples servidores (round-robin o anycast), el ETag debe ser el mismo en todos los nodos para el mismo recurso. Si el ETag se genera basándose en el inode del archivo y el sitio está desplegado en varios servidores, los valores diferirán. La solución es usar un hash del contenido o un almacenamiento centralizado de versiones (Redis, etcd). El segundo problema es la compresión gzip: Nginx cambia el ETag cuando la compresión está habilitada, lo que puede provocar 304 redundantes. Es necesario configurar gzip_vary on para sincronizar el ETag con el contenido comprimido.

Preguntas frecuentes

¿Puede el ETag ser el mismo para diferentes recursos?

Sí, si el servidor no lo ha prevenido explícitamente. Un ETag no tiene que ser globalmente único: es único dentro de una URL específica. Para archivos estáticos, las colisiones son poco probables al usar un hash SHA, pero los generadores personalizados pueden producir duplicados.

¿Es necesario configurar ETag para cada recurso?

ETag es más efectivo para recursos que se solicitan repetidamente y rara vez cambian: archivos estáticos, listas de API, configuraciones. Para páginas únicas que se cargan una vez (por ejemplo, una página de confirmación de pedido), ETag no ofrece ventajas.

¿Cómo funciona ETag con CDN?

Las CDN consideran el ETag en las solicitudes al origen para verificar la vigencia de la caché. Si el ETag de un recurso en el origen ha cambiado, la CDN carga la nueva versión. Cloudflare y Fastly soportan ETag como un mecanismo estándar de invalidación de caché a nivel de origen.

¿Puede un ETag tener más de 255 caracteres?

RFC 7232 no limita la longitud del ETag, pero los servidores y proxies pueden truncar o ignorar valores excesivamente largos. Se recomienda usar un hash de 20–40 caracteres o una combinación de identificador de versión y suma de verificación.

¿Qué elegir: ETag o Cache-Control?

No son mecanismos mutuamente excluyentes. Cache-Control define la política de almacenamiento en caché (cuánto tiempo almacenar, quién puede hacerlo), mientras que ETag es un mecanismo de validación de recursos en caché. La configuración óptima incluye ambos encabezados juntos.

Resumen

  • ETag — un encabezado HTTP con un identificador único de versión de recurso para solicitudes condicionales y almacenamiento en caché eficiente
  • Principio — el cliente envía If-None-Match con el ETag guardado, el servidor responde con 304 si coinciden
  • ETags fuertes — identidad byte a byte para archivos estáticos, débiles — equivalencia semántica para APIs
  • ETag es más preciso que Last-Modified — rastrea el contenido, no la fecha, y cambia solo con modificaciones reales
  • Uso combinado con Last-Modified brinda la máxima eficiencia de caché
  • Lado del servidor — generación mediante hash del contenido, número de versión de datos o combinación de parámetros
  • Recomendación — usar ETag para todos los endpoints de API y recursos estáticos en aplicaciones móviles

Desarrollaremos una aplicación móvil llave en mano

IT Sectr crea aplicaciones para iOS y Android para startups y empresas desde 2017. Le asesoraremos y le propondremos la mejor solución.

Discutir el proyecto

Lea también