Backend Kotlin (API, sécurité, jobs images), intégration front PWA et pipeline CI/CD
API marketplace — compression WebP et CSRF distribué
Monolithe Spring Boot + PWA React : images remplacées en WebP seulement si plus légères, CSRF partagé via Redis, déploiement conteneurisé automatisé.
- 40-45 %
- réduction moyenne (images déjà compactes)
- 98,5 %
- réduction sur photo source non optimisée
- 1024 px
- redimensionnement max avant encodage
Contexte
Plateforme marketplace (espaces / produits / modération) : API unique Spring Boot, front React/Vite, back-office admin, déploiement conteneurisé. Redis est obligatoire pour le CSRF et le cache entre instances.
Le problème
Les images produits gonflaient le stockage objet et la bande passante ; une compression naïve pouvait produire un WebP plus lourd que l'original. En parallèle, un store CSRF en mémoire cassait les POST authentifiés dès qu'il y avait plusieurs instances derrière le reverse-proxy.
L'approche
- Encodeur WebP côté backend (qualité 0,8) avec règle explicite : ne remplacer le fichier objet et la référence DB que si le WebP est strictement plus léger ; sinon conserver l'original.
- Job async de compression admin (suivi de tâche, journal des skips « WebP plus lourd »).
- CSRF via Redis (`csrf:{sessionId}`) pour partager les tokens entre instances ; PostgreSQL pour le métier, Redis pour état de session/cache.
- CI GitHub Actions : build Docker multi-stage, push vers un registre de conteneurs, déclenchement webhook de déploiement sur main ; front en PWA (vite-plugin-pwa / Workbox) pour le shell installable.
Pourquoi ce choix
Conserver l'original quand le WebP n'apporte rien évite de dégrader la taille « pour le principe ». Redis pour le CSRF plutôt qu'un sticky-session seul : les instances restent interchangeables derrière le reverse-proxy.
Résultat mesuré
- Réduction moyenne de 40 à 45 % sur des images déjà compactes (15-170 Ko), jusqu'à 65 % sur les plus lourdes de cet échantillon
- Jusqu'à 98,5 % de réduction sur une photo source non optimisée (smartphone, plusieurs Mo), portée surtout par le redimensionnement à 1024 px
- Skip automatique si le WebP produit un fichier plus lourd que l'original — aucun cas rencontré sur les échantillons testés