Invalidation du cache — le processus de suppression ou de mise à jour des données obsolètes dans le cache pour garantir la pertinence des informations reçues par l'application. Dans le développement mobile, l'invalidation est cruciale : l'utilisateur s'attend à des données fraîches sans rechargement complet. Selon Google Developers, 2025, une invalidation correctement configurée réduit les requêtes réseau de 60 % et améliore la réactivité de l'interface.
Points clés
Invalidation du cache est le processus d'invalidation ou de mise à jour des entrées en cache qui ne correspondent plus à l'état actuel de la source de données. Contrairement au nettoyage manuel de l'intégralité du cache, l'invalidation fonctionne de manière sélective : seules les données dont la pertinence est douteuse.
Le cache stocke des copies de données pour un accès rapide. Avec le temps, les données originales dans la base de données ou sur le serveur peuvent changer — par exemple, un utilisateur a mis à jour son profil ou un nouveau post est apparu dans le fil. Si le cache n'est pas invalidé, l'application affichera des informations obsolètes, ce qui dans les applications mobiles entraîne des erreurs de transaction, un affichage incorrect et une perte de confiance.
La principale difficulté de toute invalidation est le dicton bien connu : « There are only two hard things in Computer Science: cache invalidation and naming things ». La complexité réside dans le fait que le cache ne sait pas quand la source a changé, à moins d'en être explicitement informé.
Selon Martin Kleppmann, auteur de « Designing Data-Intensive Applications » (O'Reilly, 2017), une invalidation correcte nécessite soit une notification centralisée des changements, soit un mécanisme de vérification de la pertinence à chaque lecture — un compromis entre performance et cohérence.
data class CacheEntryT(
val data: T,
val expiresAt: Long,
val version: Int = 0
)
fun CacheT.isValid(key: String): Boolean =
get(key)?.let { it.expiresAt > currentTimeMillis() && it.version == currentVersion(key) } ?: false
Ce code montre une approche simple : une entrée en cache est considérée comme valide si le TTL n'a pas expiré et que la version correspond à la version actuelle dans la source. Le mécanisme de versionnement est l'un des moyens fiables d'éviter l'affichage de données obsolètes.
L'actualité des données est une exigence clé pour la plupart des applications mobiles : réseaux sociaux, messageries, services bancaires, plateformes de commerce électronique. Un utilisateur qui voit un solde de compte incorrect ou d'anciens messages perd confiance dans l'application.
En plus de l'expérience utilisateur, l'invalidation économise du trafic et de la batterie. Au lieu de recharger périodiquement toutes les données, une application mobile peut invalider uniquement les entrées modifiées et les charger sélectivement. Selon Meta Engineering (2024), la mise en œuvre de l'invalidation incrémentielle dans Facebook Lite a réduit la consommation de trafic de 35 % sans perte d'actualité du contenu.
Un autre aspect important est la cohérence des transactions. Dans les applications avec panier d'achat ou système de réservation, l'utilisation d'un cache obsolète peut entraîner des doubles facturations ou des conflits de données. L'invalidation après des opérations critiques garantit que la prochaine requêTE lira des données fraîches.
TTL est la stratégie la plus simple, où chaque entrée en cache reçoit une durée de vie fixe. Lorsque le TTL expire, les données sont considérées comme obsolètes et sont supprimées à la prochaine lecture. TTL est idéal pour les données mises à jour selon un calendrier — par exemple, la météo ou les taux de change. Inconvénient : les données peuvent être obsolètes dans l'intervalle TTL.
Avec la stratégie Write-Through, chaque modification de données passe par le cache : l'écriture est effectuée simultanément dans le cache et dans la source. Cela garantit que le cache contient toujours la version actuelle. L'inconvénient est une latence d'écriture accrue, car l'opération ne se termine pas tant que la source n'a pas confirmé. Write-Through convient aux données critiques pour la cohérence : solde du compte, statut de la commande.
Write-Behind est une écriture asynchrone : les données vont immédiatement dans le cache et sont écrites dans la source plus tard par un processus séparé. Cela offre des performances d'écriture élevées mais comporte un risque de perte de données en cas de panne avant la synchronisation. Dans les applications mobiles, Write-Behind est souvent utilisé pour les analyses, les journaux et les actions utilisateur non critiques.
Write-Invalidate — au lieu de mettre à jour le cache lors d'une modification des données, il supprime (invalide) simplement l'entrée correspondante. La prochaine lecture détectera un échec de cache et chargera des données fraîches depuis la source. Cette stratégie est simple à implémenter et fonctionne bien lorsque les requêtes de lecture sont nettement plus nombreuses que les requêtes d'écriture.
| Stratégie | Performances de lecture | Performances d'écriture | Cohérence |
|---|---|---|---|
| TTL | Élevées | Élevées | Faible (obsolète possible) |
| Write-Through | Élevées | Moyennes | Forte |
| Write-Behind | Élevées | Élevées | Faible (perte possible) |
| Write-Invalidate | Moyennes | Élevées | Forte (à la lecture suivante) |
Le choix de la stratégie dépend de ce qui est le plus important pour un scénario donné : la vitesse de réponse, la cohérence ou les économies de ressources. Les approches hybrides — par exemple, TTL avec Write-Invalidate à la réception d'une notification push — offrent un équilibre optimal.
Cache HTTP est le premier niveau côté client. Le navigateur ou l'application mobile stocke les réponses du serveur avec les en-têtes Cache-Control et ETag. L'invalidation se produit à la réception d'une réponse 304 Not Modified ou à l'expiration de max-age. ETag permet au client de vérifier l'actualité de la ressource sans télécharger la réponse complète.
Cache de l'application est le deuxième niveau, géré par le code : caches en mémoire (LRU, LruCache dans Android) ou sur disque (SQLite, Room, Realm). L'invalidation ici est contrôlée par le développeur. Selon Android Developers (2025), l'utilisation correcte de Room avec Flow et l'invalidation basée sur des déclencheurs réduit les redessinages de l'interface de 40 %.
Cache du serveur est le troisième niveau : Redis, Memcached, CDN. À ce niveau, l'invalidation est effectuée via TTL, les commandes DEL/PURGE ou les courtiers de messages (RabbitMQ, Kafka). L'invalidation CDN est un défi distinct : en raison de la nature distribuée du CDN, une commande de purge peut prendre des minutes pour se propager mondialement. Selon Cloudflare (2024), l'invalidation via Purge by URL prend en moyenne 5 à 15 secondes pour une propagation mondiale.
Pour coordonner l'invalidation à tous les niveaux, un service de cache centralisé ou un courtier d'événements est utilisé. Lorsque les données changent, la source publie un événement et chaque niveau reçoit une commande pour invalider des clés spécifiques. Cela évite une situation où un niveau a déjà mis à jour les données tandis qu'un autre continue de servir la version obsolète.
TTL trop long est l'erreur la plus courante. Les développeurs définissent un TTL avec une marge, ce qui fait que les utilisateurs voient des données obsolètes pendant des heures ou des jours. Solution : commencez avec un TTL court (1 à 5 minutes) et augmentez-le seulement après avoir mesuré le besoin réel.
Invalider tout le cache lors d'un seul changement est un problème typique dans l'architecture de microservices. Un utilisateur met à jour son avatar et le cache est invalidé pour tout le monde. Avec un grand nombre d'utilisateurs, cela provoque un Cache Stampede — une avalanche de requêtes vers la source. Solution : invalider uniquement la clé de l'utilisateur spécifique, pas le cache partagé.
Absence d'invalidation lors d'erreurs d'écriture — si l'écriture dans la source échoue mais que le cache a déjà été mis à jour, l'application se retrouve dans un état incohérent. Solution : invalidation en deux phases — d'abord vider le cache, puis écrire dans la source, et annuler l'invalidation en cas d'erreur.
Ignorer la nature distribuée — dans un environnement en cluster, l'invalidation sur un nœud ne signifie pas que les autres nœuds ont reçu la commande. Sans courtier d'événements, certains serveurs continueront de servir des données obsolètes. Redis Pub/Sub ou Apache Kafka résolvent ce problème en diffusant des événements d'invalidation.
Déterminez les exigences d'actualité — à quel point il est critique que les données soient à jour « tout de suite ». Pour un fil d'actualités, un retard de 1 à 2 minutes est acceptable (TTL). Pour un solde de compte, le retard est inacceptable (Write-Through).
Évaluez la fréquence des changements — les données qui sont mises à jour une fois par jour (catalogue de produits, répertoire de villes) fonctionnent bien avec TTL. Les données qui changent des dizaines de fois par seconde (statuts en ligne, taux de change) nécessitent une invalidation push via WebSockets ou Firebase Cloud Messaging.
Tenez compte du coût de lecture de la source — si la source est une requête SQL coûteuse sur 10 tables ou une API externe avec des limites, utilisez une mise en cache agressive avec un TTL long, mais compensez les données obsolètes par une invalidation push. Si la lecture est bon marché (recherche en mémoire), utilisez un TTL court et Write-Invalidate.
Selon Google I/O (2025), le modèle typique pour les applications mobiles est Stale-While-Revalidate : l'utilisateur voit instantanément les données en cache tandis que l'application vérifie leur actualité en arrière-plan et les met à jour. Cela combine vitesse de réponse et actualité sans compromis. L'en-tête HTTP Cache-Control avec la directive stale-while-revalidate est pris en charge à partir d'Android 10 et d'iOS 13.
Questions fréquentes
L'invalidation consiste à marquer un enregistrement spécifique comme obsolète, après quoi il est mis à jour à la prochaine lecture. Le vidage du cache est la suppression complète de toutes les entrées, ce qui est plus coûteux et peut temporairement réduire les performances de l'application.
ETag est un hachage ou une version d'une ressource que le serveur retourne dans un en-tête HTTP. Lors d'une requête répétée, le client envoie If-None-Match avec l'ETag actuel. Si la ressource n'a pas changé, le serveur répond avec 304 Not Modified et le cache reste valide.
Write-Through avec versionnement est la plus fiable, car les données sont toujours cohérentes. Mais elle a la latence d'écriture la plus élevée. En pratique, TTL avec invalidation push est plus souvent utilisé pour équilibrer performances et actualité.
Utilisez Probabilistic Early Expiration — chaque requête vérifie aléatoirement l'actualité du cache avant l'expiration du TTL. L'algorithme XFetch (Vattani, 2015) calcule la probabilité de recalcul avec la formule : p = (ttl — age) / (ttl * beta).
Utilisez des outils de débogage réseau : Charles Proxy, Proxyman ou l'inspecteur réseau intégré dans Android Studio et Xcode. Vérifiez qu'après modification des données, la requête suivante charge bien la nouvelle version au lieu de retourner la version mise en cache.
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