TTL (Time To Live) es un parámetro que determina el tiempo máximo durante el cual los datos se consideran válidos. Después de que el TTL expira, el registro se marca como obsoleto (stale) y debe eliminarse o actualizarse. Según Mozilla Developer Network (2026), el mecanismo TTL es la base del almacenamiento en caché HTTP a través del encabezado Cache-Control: max-age y se utiliza en todos los navegadores modernos y aplicaciones móviles para optimizar las solicitudes de red.
Puntos Clave
TTL (Time To Live) es una marca de tiempo o intervalo después del cual los datos se consideran no válidos. En el contexto del almacenamiento en caché, el TTL determina cuánto tiempo puede almacenarse un registro en la caché antes de que sea necesario volver a solicitarlo desde la fuente. En los protocolos de red, el TTL limita la vida útil de un paquete, evitando el enrutamiento infinito.
El valor TTL siempre se expresa en unidades de tiempo: milisegundos, segundos, minutos u horas. Una vez transcurrido el tiempo establecido, el registro se elimina de la caché o se marca como obsoleto. En la siguiente solicitud a un registro obsoleto, el sistema puede devolver los datos obsoletos con una actualización posterior (stale-while-revalidate) o bloquear la solicitud hasta que se obtengan datos nuevos.
Elegir el TTL es siempre un equilibrio entre la actualidad de los datos y el rendimiento. Un TTL demasiado corto (1–5 segundos) obliga a la aplicación a realizar solicitudes de red frecuentes, anulando el beneficio del almacenamiento en caché. Un TTL demasiado largo (horas/días) aumenta el riesgo de mostrar información desactualizada al usuario. El valor óptimo depende del tipo de datos: tasas de cambio — segundos, clima — minutos, versión de API — horas.
TTL es invalidación pasiva: los datos se eliminan automáticamente después de un período de tiempo. La alternativa es la invalidación activa, donde la fuente de datos notifica a la caché sobre los cambios (por ejemplo, a través de mensajes WebSocket o notificaciones push). La invalidación pasiva mediante TTL es más simple de implementar pero no garantiza la actualidad instantánea. La invalidación activa es más compleja pero permite mantener los datos actualizados sin las demoras propias del TTL.
El mecanismo TTL se puede implementar de dos maneras: vencimiento absoluto (absolute expiration) y vencimiento relativo (relative expiration). Con el vencimiento absoluto, el registro almacena la hora específica en que se vuelve no válido. Con el vencimiento relativo, se registran la hora de creación del registro y el TTL como un intervalo, y la verificación se realiza calculando creationTime + TTL > currentTime.
En cada solicitud a la caché, el sistema verifica el TTL de cada registro. Si el TTL ha expirado, los datos se eliminan o se marcan como obsoletos, y la solicitud se reenvía a la fuente. Para optimizar la verificación del TTL, se puede utilizar una limpieza programada (eliminación periódica de todos los registros vencidos) o una limpieza perezosa (eliminación solo cuando se accede al registro). La limpieza perezosa es más eficiente en memoria porque no requiere un subproceso en segundo plano para escanear toda la caché.
En sistemas distribuidos, el TTL también se utiliza para la resolución automática de conflictos. Por ejemplo, si dos servidores escriben simultáneamente diferentes valores para la misma clave, el registro con un TTL posterior puede considerarse prioritario. Amazon DynamoDB utiliza TTL para la eliminación automática de registros obsoletos en las tablas — esta es una funcionalidad incorporada que no requiere gestión manual.
Para mejorar el rendimiento cuando expira el TTL, se utilizan estrategias de lectura obsoleta. Stale-while-revalidate — devolver inmediatamente los datos obsoletos al cliente y lanzar simultáneamente una actualización en segundo plano. Stale-if-error — devolver datos obsoletos si la fuente no está disponible temporalmente. Cache-Aside (Lazy Loading) — ante una falla de caché, cargar los datos desde la fuente, guardarlos en la caché con un nuevo TTL y solo entonces devolverlos al cliente. Cada estrategia se elige según los requisitos de consistencia de los datos.
En las aplicaciones móviles, el TTL es un mecanismo clave para la gestión de la caché. Veamos los principales escenarios donde el TTL determina el comportamiento de la aplicación y la experiencia del usuario.
El protocolo HTTP proporciona un mecanismo TTL integrado a través de los encabezados Cache-Control. La directiva max-age establece el TTL en segundos: Cache-Control: public, max-age=3600 significa que la respuesta se puede almacenar en caché durante 1 hora. Las directivas adicionales s-maxage (para cachés compartidos, ej., CDN) y stale-while-revalidate proporcionan un control más preciso. Cuando el TTL coincide con el encabezado expires, max-age tiene prioridad como el estándar HTTP/1.1 más moderno.
| Tipo de datos | TTL recomendado | Justificación |
|---|---|---|
| Clima | 10–30 minutos | Los pronósticos se actualizan con poca frecuencia |
| Tasas de cambio | 15–60 segundos | Alta volatilidad |
| Feed de noticias | 2–5 minutos | Equilibrio entre actualidad y rendimiento |
| Perfil de usuario | 5–30 minutos | Cambia raramente durante una sesión |
| Lista de productos | 10–60 minutos | Los precios no cambian cada segundo |
| Recursos estáticos | 1–24 horas | Versionados mediante URL o ETag |
Para las imágenes, el TTL puede alcanzar varios días, ya que el contenido rara vez cambia. Sin embargo, las aplicaciones móviles suelen utilizar un enfoque híbrido: un TTL corto para las vistas previas (30 minutos — actualidad de los fotogramas) y un TTL largo para las imágenes de tamaño completo (7 días). Las imágenes con el encabezado HTTP Cache-Control: immutable no deben volverse a solicitar hasta que expire el TTL — esta es una optimización para recursos estáticos propuesta en RFC 8246. Dichas imágenes se almacenan en caché a nivel del sistema operativo (URLCache, OkHttp Cache) sin participación de la aplicación.
En las redes, el TTL no se utiliza para el almacenamiento en caché sino para limitar la vida útil de los paquetes. Cada paquete IP contiene un campo TTL (8 bits), que se reduce en 1 por cada enrutador. Cuando el TTL llega a 0, el paquete se descarta y el remitente recibe un mensaje ICMP Time Exceeded. Esto evita el enrutamiento infinito durante los bucles de red.
Los registros DNS tienen un TTL que determina cuánto tiempo un resolutor (por ejemplo, la caché DNS del ISP) puede almacenar el registro sin consultar al servidor autoritativo. Valores típicos: 300 segundos (5 minutos) para registros con cambios frecuentes, 86400 segundos (24 horas) para dominios estables. Los servicios CDN a menudo establecen un TTL bajo (60–300 segundos) para un redireccionamiento rápido del tráfico durante fallos, mientras que los dominios estáticos pueden tener un TTL de hasta 7 días. Al migrar un servidor, se recomienda primero reducir el TTL a 60 segundos (48 horas antes de la migración) para que los cambios se propaguen rápidamente.
En las aplicaciones móviles, el TTL se utiliza para gestionar sesiones y tokens de acceso. Los tokens JWT (JSON Web Tokens) contienen un campo exp (tiempo de vencimiento), que es el tiempo Unix absoluto de vencimiento. Después del vencimiento, se utiliza un token de actualización para obtener un nuevo token de acceso sin reautenticación. El TTL del token de acceso suele ser de 1–24 horas, el TTL del token de actualización es de 7–30 días. Esto es un equilibrio entre la seguridad (un TTL corto reduce el riesgo de fuga) y la UX (un TTL largo reduce la frecuencia de reinicios de sesión).
Elegir el TTL es una decisión de ingeniería que depende del tipo de datos, el SLA de actualidad y el costo de una nueva solicitud. Consideremos las principales estrategias.
El enfoque más simple — todos los registros tienen el mismo TTL. Por ejemplo, almacenar en caché todas las respuestas de API durante 5 minutos. Ventaja: simplicidad de implementación y comportamiento predecible. Desventaja: no tiene en cuenta las diferentes frecuencias de cambio de los distintos tipos de datos. El TTL fijo está justificado para datos homogéneos donde todos los registros tienen la misma «actualidad» — por ejemplo, las tasas de criptomonedas en un mismo exchange.
El TTL cambia dinámicamente según el comportamiento de los datos. Por ejemplo, si un registro se actualiza raramente en el servidor, el TTL aumenta; si se actualiza con frecuencia, disminuye. La implementación puede utilizar los encabezados de respuesta HTTP: el encabezado Age (cuántos segundos la respuesta ya ha estado en la caché) y el encabezado Date permiten calcular el tiempo de vida restante. El TTL adaptativo proporciona una mejor tasa de aciertos pero requiere lógica adicional en el cliente.
Probabilistic Early Expiration (PEE) — una técnica donde el TTL se elige aleatoriamente dentro de un rango dado. Esto evita el efecto «manada atronadora» (thundering herd), donde muchas solicitudes expiran simultáneamente y todos los clientes acceden a la fuente al mismo tiempo. PEE es especialmente útil para CDN y cachés de alta carga: en lugar de un único TTL de 300 segundos, se utiliza un valor aleatorio de 240 a 360 segundos, distribuyendo la carga en la fuente de manera uniforme.
Veamos una implementación de caché con TTL en Kotlin utilizando vencimiento absoluto. Cada registro almacena su hora de creación y, al leer, se verifica si el TTL ha expirado.
class TtlCache<K, V>(
private val defaultTtlMs: Long = 300000L
) {
private data class Entry<V>(
val value: V,
val createdAt: Long = System.currentTimeMillis()
)
private val map = ConcurrentHashMap<K, Entry<V>>()
fun get(key: K): V? {
val entry = map[key] ?: return null
if (isExpired(entry)) {
map.remove(key)
return null
}
return entry.value
}
fun put(key: K, value: V, ttlMs: Long = defaultTtlMs) {
map[key] = Entry(value, createdAt = System.currentTimeMillis() + ttlMs)
}
private fun isExpired(entry: Entry<*>): Boolean {
return System.currentTimeMillis() > entry.createdAt
}
fun cleanup() {
map.entries.removeIf { isExpired(it.value) }
}
}
La clase Entry almacena el valor y la hora de creación + TTL (vencimiento absoluto). El método get verifica el vencimiento en cada acceso (limpieza perezosa) — los registros vencidos solo se eliminan cuando se intenta acceder a ellos. El método cleanup se puede llamar periódicamente desde un subproceso en segundo plano para eliminar por lotes todos los registros obsoletos. ConcurrentHashMap proporciona seguridad en los subprocesos sin bloquear toda la caché.
En iOS, es conveniente usar URLCache con las configuraciones memoryCapacity y diskCapacity para el almacenamiento en caché con TTL. Sin embargo, URLCache no admite TTL individual para diferentes solicitudes. Consideremos un envoltorio personalizado de NSCache con soporte de TTL.
final class ApiResponseCache {
private var cache = NSCache<NSString, CacheEntry>()
func getResponse(for url: URL) -> Data? {
guard let entry = cache.object(forKey: url.absoluteString as NSString)
else { return nil }
guard entry.expirationDate > Date() else {
cache.removeObject(forKey: url.absoluteString as NSString)
return nil
}
return entry.data
}
func storeResponse(data: Data, for url: URL, ttl: TimeInterval) {
let entry = CacheEntry(data: data, expirationDate: Date().addingTimeInterval(ttl))
cache.setObject(entry, forKey: url.absoluteString as NSString)
}
}
final class CacheEntry: NSObject {
let data: Data
let expirationDate: Date
}
En esta implementación, NSCache se utiliza como almacenamiento seguro para subprocesos. CacheEntry contiene Data y expirationDate. Cuando se llama a get, se verifica si el tiempo ha expirado; si es así, el registro se elimina y se devuelve nil. El TTL se establece en segundos mediante TimeInterval y puede ser diferente para cada URL: los valores típicos para respuestas de API son 120 segundos para contenido dinámico y 3600 para datos estáticos.
Preguntas Frecuentes
Técnicamente, TTL y fecha de vencimiento son lo mismo: un intervalo de tiempo después del cual los datos se consideran no válidos. La diferencia está en el contexto: el término TTL se utiliza en TI (caché, redes, DNS), mientras que «fecha de vencimiento» se aplica más a menudo en la lógica de negocio (códigos promocionales, suscripciones). En la implementación, ambos mecanismos son idénticos — comparación de la hora actual con la hora de vencimiento.
El TTL óptimo se elige empíricamente. Metodología: comenzar con un valor conservador (30–60 segundos), aumentar gradualmente hasta que aparezcan quejas sobre datos desactualizados. Monitorear la tasa de aciertos de la caché: si es inferior al 70%, el TTL es demasiado corto. Considere el SLA: para datos financieros, el TTL puede ser de 1 segundo; para noticias — 5 minutos; para perfiles — 30 minutos.
Después de que expira max-age, el navegador o la aplicación móvil considera la respuesta obsoleta. En la siguiente solicitud a la misma URL, el cliente envía una solicitud con el encabezado If-None-Match (ETag) o If-Modified-Since. Si los datos no han cambiado, el servidor devuelve 304 Not Modified sin cuerpo de respuesta y el TTL se actualiza. Si han cambiado, el servidor devuelve 200 con nuevos datos y un nuevo Cache-Control.
Técnicamente, el TTL puede ser muy grande (max-age=31536000 — 1 año), pero esto rara vez está justificado. Incluso los recursos estáticos pueden cambiar, y el cliente no lo sabrá hasta que expire el TTL. Se recomienda usar URLs versionadas (style.css?v=2) con un TTL largo: cuando el archivo cambia, la URL cambia y la caché antigua se vuelve obsoleta automáticamente.
TTL y las estrategias de desalojo (LRU, FIFO) resuelven problemas diferentes. TTL determina cuándo los datos se vuelven irrelevantes — este es un criterio temporal. LRU y FIFO determinan qué datos eliminar cuando la caché está llena — este es un criterio espacial. Pueden combinarse: un registro se elimina si el TTL ha expirado O la caché está llena (por LRU/FIFO). En sistemas de producción, ambos mecanismos funcionan juntos.
Resumen
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.
Lea también