TTL (Time To Live) est un paramètre qui détermine la durée maximale pendant laquelle les données sont considérées comme valides. Après l’expiration du TTL, l’enregistrement est marqué comme obsolète (stale) et doit être supprimé ou mis à jour. Selon Mozilla Developer Network (2026), le mécanisme TTL est le fondement de la mise en cache HTTP via l’en-tête Cache-Control: max-age et est utilisé dans tous les navigateurs modernes et applications mobiles pour optimiser les requêtes réseau.
Points clés
TTL (Time To Live) est un horodatage ou un intervalle après lequel les données sont considérées comme invalides. Dans le contexte de la mise en cache, le TTL détermine combien de temps un enregistrement peut être stocké dans le cache avant de devoir être re-demander à la source. Dans les protocoles réseau, le TTL limite la durée de vie d’un paquet, empêchant le routage infini.
La valeur TTL est toujours exprimée en unités de temps : millisecondes, secondes, minutes ou heures. Après l’expiration du temps défini, l’enregistrement est soit supprimé du cache, soit marqué comme obsolète. Lors de la requête suivante d’un enregistrement obsolète, le système peut soit renvoyer les données obsolètes avec une mise à jour ultérieure (stale-while-revalidate), soit bloquer la requête jusqu’à l’obtention de données fraîches.
Choisir le TTL est toujours un compromis entre la fraîcheur des données et les performances. Un TTL trop court (1–5 secondes) force l’application à effectuer des requêtes réseau fréquentes, annulant l’avantage de la mise en cache. Un TTL trop long (heures/jours) augmente le risque d’afficher des informations obsolètes à l’utilisateur. La valeur optimale dépend du type de données : taux de change — secondes, météo — minutes, version API — heures.
TTL est une invalidation passive : les données sont automatiquement supprimées après une période. L’alternative est l’invalidation active, où la source de données notifie le cache des changements (par exemple, via des messages WebSocket ou des notifications push). L’invalidation passive via TTL est plus simple à implémenter mais ne garantit pas une fraîcheur instantanée. L’invalidation active est plus complexe mais permet de maintenir les données à jour sans les retards inhérents au TTL.
Le mécanisme TTL peut être implémenté de deux manières : l’expiration absolue (absolute expiration) et l’expiration relative (relative expiration). Avec l’expiration absolue, l’enregistrement stocke l’heure spécifique à laquelle il deviendra invalide. Avec l’expiration relative, l’heure de création de l’enregistrement et le TTL comme intervalle sont enregistrés, et la vérification est effectuée en calculant creationTime + TTL > currentTime.
À chaque requête au cache, le système vérifie le TTL de chaque enregistrement. Si le TTL a expiré, les données sont supprimées ou marquées comme obsolètes, et la requête est transmise à la source. Pour optimiser la vérification du TTL, on peut utiliser un nettoyage planifié (suppression périodique de tous les enregistrements expirés) ou un nettoyage paresseux (suppression uniquement lors de l’accès à l’enregistrement). Le nettoyage paresseux est plus efficace en mémoire car il ne nécessite pas de thread d’arrière-plan pour analyser l’intégralité du cache.
Dans les systèmes distribués, TTL est également utilisé pour la résolution automatique des conflits. Par exemple, si deux serveurs écrivent simultanément des valeurs différentes pour la même clé, l’enregistrement avec le TTL le plus récent peut être considéré comme prioritaire. Amazon DynamoDB utilise TTL pour la suppression automatique des enregistrements obsolètes dans les tables — c’est une fonctionnalité intégrée qui ne nécessite pas de gestion manuelle.
Pour améliorer les performances lors de l’expiration du TTL, des stratégies de lecture obsolète sont utilisées. Stale-while-revalidate — renvoyer immédiatement les données obsolètes au client et lancer simultanément une mise à jour en arrière-plan. Stale-if-error — renvoyer les données obsolètes si la source est temporairement indisponible. Cache-Aside (Lazy Loading) — en cas d’absence dans le cache, charger les données depuis la source, les sauvegarder dans le cache avec un nouveau TTL, puis les renvoyer au client. Chaque stratégie est choisie en fonction des exigences de cohérence des données.
Dans les applications mobiles, TTL est un mécanisme clé pour la gestion du cache. Examinons les principaux scénarios où TTL détermine le comportement de l’application et l’expérience utilisateur.
Le protocole HTTP fournit un mécanisme TTL intégré via les en-têtes Cache-Control. La directive max-age définit le TTL en secondes : Cache-Control: public, max-age=3600 signifie que la réponse peut être mise en cache pendant 1 heure. Les directives supplémentaires s-maxage (pour les caches partagés, ex : CDN) et stale-while-revalidate offrent un contrôle plus fin. Lorsque TTL coïncide avec l’en-tête expires, max-age a la priorité en tant que norme HTTP/1.1 plus moderne.
| Type de données | TTL recommandé | Justification |
|---|---|---|
| Météo | 10–30 minutes | Les prévisions ne sont pas mises à jour fréquemment |
| Taux de change | 15–60 secondes | Forte volatilité |
| Flux d’actualités | 2–5 minutes | Équilibre entre fraîcheur et performances |
| Profil utilisateur | 5–30 minutes | Change rarement pendant une session |
| Liste de produits | 10–60 minutes | Les prix ne changent pas chaque seconde |
| Ressources statiques | 1–24 heures | Versionnées via URL ou ETag |
Pour les images, le TTL peut atteindre plusieurs jours car le contenu change rarement. Cependant, les applications mobiles utilisent souvent une approche hybride : un TTL court pour les aperçus (30 minutes — fraîcheur des images) et un TTL long pour les images pleine taille (7 jours). Les images avec l’en-tête HTTP Cache-Control: immutable ne doivent pas être re-demandées jusqu’à l’expiration du TTL — c’est une optimisation pour les ressources statiques proposée dans la RFC 8246. Ces images sont mises en cache au niveau du système d’exploitation (URLCache, OkHttp Cache) sans intervention de l’application.
Dans les réseaux, TTL n’est pas utilisé pour la mise en cache mais pour limiter la durée de vie des paquets. Chaque paquet IP contient un champ TTL (8 bits), qui est diminué de 1 par chaque routeur. Lorsque TTL atteint 0, le paquet est rejeté et l’expéditeur reçoit un message ICMP Time Exceeded. Cela empêche le routage infini lors des boucles réseau.
Les enregistrements DNS ont un TTL qui détermine combien de temps un résolveur (par exemple, le cache DNS du FAI) peut stocker l’enregistrement sans interroger le serveur faisant autorité. Valeurs typiques : 300 secondes (5 minutes) pour les enregistrements avec des changements fréquents, 86400 secondes (24 heures) pour les domaines stables. Les services CDN définissent souvent un TTL bas (60–300 secondes) pour une redirection rapide du trafic lors de pannes, tandis que les domaines statiques peuvent avoir un TTL allant jusqu’à 7 jours. Lors de la migration d’un serveur, il est recommandé d’abord de réduire le TTL à 60 secondes (48 heures avant la migration) pour que les changements se propagent rapidement.
Dans les applications mobiles, TTL est utilisé pour gérer les sessions et les jetons d’accès. Les jetons JWT (JSON Web Tokens) contiennent un champ exp (temps d’expiration), qui est le temps d’expiration absolu Unix. Après l’expiration, un jeton d’actualisation est utilisé pour obtenir un nouveau jeton d’accès sans ré-authentification. Le TTL du jeton d’accès est généralement de 1 à 24 heures, le TTL du jeton d’actualisation est de 7 à 30 jours. C’est un équilibre entre sécurité (TTL court réduit le risque de fuite) et UX (TTL long réduit la fréquence des reconnexions).
Choisir le TTL est une décision d’ingénierie qui dépend du type de données, du SLA de fraîcheur et du coût d’une nouvelle requête. Examinons les principales stratégies.
L’approche la plus simple — tous les enregistrements ont le même TTL. Par exemple, mettre en cache toutes les réponses API pendant 5 minutes. Avantage : simplicité d’implémentation et comportement prévisible. Inconvénient : ne tient pas compte des différentes fréquences de changement des différents types de données. Le TTL fixe est justifié pour des données homogènes où tous les enregistrements ont la même « fraîcheur » — par exemple, les taux de crypto-monnaies sur un même échange.
TTL change dynamiquement en fonction du comportement des données. Par exemple, si un enregistrement est rarement mis à jour sur le serveur, TTL augmente ; s’il est mis à jour fréquemment, il diminue. L’implémentation peut utiliser les en-têtes de réponse HTTP : l’en-tête Age (combien de secondes la réponse a déjà passé dans le cache) et l’en-tête Date permettent de calculer la durée de vie restante. TTL adaptatif offre un meilleur taux de succès mais nécessite une logique supplémentaire sur le client.
Probabilistic Early Expiration (PEE) — une technique où TTL est choisi aléatoirement dans une plage donnée. Cela empêche l’effet de « ruée vers la source » (thundering herd), où de nombreuses requêtes expirent simultanément et tous les clients accèdent à la source en même temps. PEE est particulièrement utile pour les CDN et les caches à forte charge : au lieu d’un seul TTL de 300 secondes, une valeur aléatoire de 240 à 360 secondes est utilisée, répartissant la charge sur la source de manière uniforme.
Voyons une implémentation de cache avec TTL en Kotlin utilisant l’expiration absolue. Chaque enregistrement stocke son heure de création, et à la lecture, on vérifie si le TTL a expiré.
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 classe Entry stocke la valeur et l’heure de création + TTL (expiration absolue). La méthode get vérifie l’expiration à chaque accès (nettoyage paresseux) — les enregistrements expirés ne sont supprimés que lorsqu’on tente d’y accéder. La méthode cleanup peut être appelée périodiquement depuis un thread d’arrière-plan pour supprimer par lot tous les enregistrements obsolètes. ConcurrentHashMap assure la sécurité des threads sans verrouiller l’intégralité du cache.
Sur iOS, il est pratique d’utiliser URLCache avec les paramètres memoryCapacity et diskCapacity pour la mise en cache avec TTL. Cependant, URLCache ne prend pas en charge un TTL individuel pour différentes requêtes. Considérons un wrapper personnalisé de NSCache avec prise en charge 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
}
Dans cette implémentation, NSCache est utilisé comme stockage thread-safe. CacheEntry contient Data et expirationDate. Lorsque get est appelé, on vérifie si le temps a expiré ; si oui, l’enregistrement est supprimé et nil est renvoyé. Le TTL est défini en secondes via TimeInterval et peut être différent pour chaque URL : les valeurs typiques pour les réponses API sont de 120 secondes pour le contenu dynamique et 3600 pour les données statiques.
Questions fréquentes
Techniquement, TTL et date d’expiration sont la même chose : un intervalle de temps après lequel les données sont considérées comme invalides. La différence réside dans le contexte : le terme TTL est utilisé en informatique (cache, réseaux, DNS), tandis que « date d’expiration » est plus souvent appliqué dans la logique métier (codes promo, abonnements). Dans l’implémentation, les deux mécanismes sont identiques — comparaison de l’heure actuelle avec l’heure d’expiration.
Le TTL optimal est choisi empiriquement. Méthodologie : commencer par une valeur prudente (30–60 secondes), augmenter progressivement jusqu’à l’apparition de plaintes concernant des données obsolètes. Surveiller le taux de succès du cache : s’il est inférieur à 70 %, le TTL est trop court. Tenir compte du SLA : pour les données financières, le TTL peut être de 1 seconde ; pour les actualités — 5 minutes ; pour les profils — 30 minutes.
Après l’expiration de max-age, le navigateur ou l’application mobile considère la réponse comme obsolète. Lors de la requête suivante à la même URL, le client envoie une requête avec l’en-tête If-None-Match (ETag) ou If-Modified-Since. Si les données n’ont pas changé, le serveur renvoie 304 Not Modified sans corps de réponse, et le TTL est mis à jour. Si elles ont changé, le serveur renvoie 200 avec de nouvelles données et un nouveau Cache-Control.
Techniquement, TTL peut être très grand (max-age=31536000 — 1 an), mais c’est rarement justifié. Même les ressources statiques peuvent changer, et le client ne le saura pas avant l’expiration du TTL. Il est recommandé d’utiliser des URLs versionnées (style.css?v=2) avec un TTL long : lorsque le fichier change, l’URL change et le cache ancien devient automatiquement obsolète.
TTL et les stratégies d’éviction (LRU, FIFO) résolvent des problèmes différents. TTL détermine quand les données deviennent hors de propos — c’est un critère temporel. LRU et FIFO déterminent quelles données supprimer lorsque le cache est plein — c’est un critère spatial. Ils peuvent être combinés : un enregistrement est supprimé si TTL a expiré OU si le cache est plein (par LRU/FIFO). Dans les systèmes de production, les deux mécanismes fonctionnent ensemble.
Résumé
Nous développerons une application mobile clé en main
IT Sectr crée des applications iOS et Android pour les startups et les entreprises depuis 2017. Nous vous conseillerons et vous proposerons la meilleure solution.
Lisez aussi