Hamed Cédric SYLLA

🧠 Spring Boot – Optimisation des performances avec Spring Cache

đŸȘ§ Introduction

Tu as dĂ©jĂ  eu une API lente Ă  cause de requĂȘtes rĂ©pĂ©titives en base ?

👉 Exemple classique :

  • Une mĂ©thode appelĂ©e 100 fois
  • Qui fait toujours la mĂȘme requĂȘte
  • Avec toujours le mĂȘme rĂ©sultat

Résultat :
đŸ’„ surcharge inutile de la base
đŸ’„ latence qui explose
đŸ’„ scalabilitĂ© limitĂ©e

Et pourtant
 Spring Boot propose un systĂšme de cache natif ultra simple Ă  activer.

Dans cet article, on va voir :

  • Pourquoi utiliser le cache
  • Comment fonctionne le cache natif de Spring Boot
  • Comment l’implĂ©menter rapidement
  • Les piĂšges Ă  Ă©viter
  • Les limites (et pourquoi tu passeras peut-ĂȘtre Ă  Redis plus tard)

1. ⚡ Pourquoi utiliser un cache ?

Le principe est simple :
👉 Ă©viter de recalculer une donnĂ©e qui ne change pas
Sans cache :

Client → Service → DB → RĂ©sultat
Client → Service → DB → RĂ©sultat
Client → Service → DB → RĂ©sultat

Avec cache :

Client → Service → DB → RĂ©sultat (mis en cache)
Client → Service → Cache → RĂ©sultat
Client → Service → Cache → RĂ©sultat

🎯 RĂ©sultat

✔ Moins d’appels Ă  la base
✔ Temps de rĂ©ponse rĂ©duit
✔ Meilleure scalabilitĂ©

2. 🧠 Spring Cache, c’est quoi ?

Spring propose une abstraction simple via :

@EnableCaching

Et des annotations :

  • @Cacheable
  • @CacheEvict
  • @CachePut

💡 Important

Elle permet de brancher facilement diffĂ©rents systĂšmes de cache sans changer ton code mĂ©tier.
Spring Boot fonctionne avec plusieurs providers de cache (EhCache, Caffeine, Redis
).
Ici, on utilise le comportement par défaut, mais on verra dans un prochain article comment brancher un cache distribué comme Redis.

Par défaut :
âžĄïž cache en mĂ©moire basĂ© sur une ConcurrentHashMap

3. đŸ‘šâ€đŸ’» Mise en place du cache

Étape 1 – Ajouter la dĂ©pendance dans pom.xml (maven)

<dependencies>
    <dependency>
        <groupId>org.springframework.boot</groupId>
        <artifactId>spring-boot-starter-cache</artifactId>
    </dependency>
</dependencies>

Étape 2 – Activer le cache

@SpringBootApplication
@EnableCaching
public class Application {
}

Étape 3 – Ajouter du cache sur une mĂ©thode

@Cacheable("users")
public User getUserById(Long id) {
simulateSlowService();
return userRepository.findById(id).orElseThrow();
}

👉 Ce qui se passe :

  • 1er appel → DB + mise en cache
  • Appels suivants → cache direct

🔍 Par dĂ©faut, la clĂ© du cache

Spring utilise :
clé = paramÚtres de la méthode

Ici :
getUserById(1) → clĂ© = 1

4. 🎯 Les annotations essentielles

🟱 @Cacheable

👉 Met en cache le rĂ©sultat

@Cacheable("products")
public Product getProduct(Long id) { }

🔮 @CacheEvict

👉 Supprime une entrĂ©e du cache

@CacheEvict(value = "users", key = "#id")<br>public void deleteUser(Long id) { }

🟡 @CachePut

👉 Met Ă  jour le cache sans passer par @Cacheable

@CachePut(value = "users", key = "#user.id")<br>public User updateUser(User user) { }

5. ⚠ Les piĂšges classiques

1. Le cache ne fonctionne pas dans certains cas

👉 Cas trĂšs frĂ©quent :

public void methodA() {
    methodB(); // ❌ cache ignorĂ©
}

@Cacheable("data")
public String methodB() { }

đŸ’„ Pourquoi ?
âžĄïž Spring utilise des proxies
âžĄïž Les appels internes ne passent pas par le proxy

👉 Solution :

  • appeler depuis un autre bean
  • ou injecter le bean lui-mĂȘme

2. Données jamais rafraßchies

👉 Si tu caches sans Ă©viction : tu peux servir des donnĂ©es obsolĂštes

👉 Toujours rĂ©flĂ©chir Ă  :

  • quand invalider ?
  • quand mettre Ă  jour ?

3. Mauvaise clé de cache

@Cacheable("users")
public User getUser(User user)

Mauvais si equals/hashCode mal dĂ©finis

4. Cache sur des méthodes non pertinentes

Ne cache PAS :

  • des donnĂ©es trĂšs dynamiques
  • des appels uniques
  • des rĂ©sultats Ă©normes

6. ❗ Les limites du cache natif

  1. Cache local uniquement
    • Chaque instance a son cache
    • Pas partagĂ© entre plusieurs serveurs
  2. Pas de TTL natif (simple)
    • Pas d’expiration automatique facile
  3. Pas adapté aux architectures distribuées
    • Si tu passes en microservices → problĂšme
  4. Perte du cache au redémarrage

7. 🧠 Quand utiliser ce cache ?

✔ Bon cas

  • donnĂ©es rarement modifiĂ©es
  • lecture frĂ©quente
  • application simple (mono-instance)

❌ Mauvais cas

  • donnĂ©es critiques en temps rĂ©el
  • multi-instance
  • besoin de synchronisation

8. đŸ”„ Et aprĂšs ?

Quand ton application grandit, tu vas vouloir :

  • un cache partagĂ©
  • une expiration (TTL)
  • de la scalabilitĂ©

C’est là que des solutions comme Redis entrent en jeu

9. đŸ›Ąïž Bonnes pratiques

✔ Nommer clairement tes caches (usersproducts)
✔ Toujours prĂ©voir une stratĂ©gie d’invalidation
✔ Ne pas cacher « par dĂ©faut » → rĂ©flĂ©chir au besoin
✔ Monitorer les performances

🧭 Conclusion

Le cache natif de Spring Boot est :

✔ Ultra simple Ă  mettre en place
✔ Parfait pour dĂ©marrer
✔ TrĂšs efficace pour booster les performances

Mais :

❗ il montre vite ses limites en production avancĂ©e

C’est une excellente porte d’entrĂ©e avant de passer Ă  des solutions plus robustes comme Redis.

📚 Sources & lectures recommandĂ©es