Je me retrouve avec un petit souci de perf sur un projet Laravel en prod qui commence à avoir du volume (plus de 100k users actifs). Le classique problème de requêtes N+1 qui me bouffe mes performances comme un goinfre ?
Contexte rapide : j'ai une app e-commerce avec des relations User -> Orders -> OrderItems -> Products. Quand je charge la liste des commandes avec leurs détails, ça part en vrille niveau requêtes SQL.
J'ai déjà implémenté quelques trucs :
Eager loading avec with() sur les relations principales
Cache Redis pour les données produits les plus consultées
Pagination pour limiter les résultats
Mais j'ai encore des pics à 200+ requêtes sur certaines pages admin. Les lazy loading par défaut d'Eloquent, c'est pratique en dev mais en prod ça pique...
Du coup je me demandais :
Vous utilisez quoi comme tools pour tracker ces problèmes ? (Telescope c'est cool mais ça reste basique)
Des retours d'expérience sur withCount() vs des requêtes SQL custom ?
Vous passez par des Repository patterns ou vous restez sur les Models Eloquent ?
J'hésite aussi à migrer certaines parties critiques vers du Query Builder pur, mais j'aimerais garder la lisibilité d'Eloquent si possible.
Des suggestions d'approches qui ont fait leurs preuves chez vous ? Surtout côté monitoring en continu, parce que repérer ces trucs après coup c'est toujours galère.
Merci d'avance pour vos retours ! ?
[i]Code is poetry, coffee is fuel ☕[/i] - [url=https://github.com/freelanceenpyjama]Mon GitHub[/url]
Salut ! Ton cas me rappelle un projet similaire qu'on a eu l'année dernière. Au delà de l'eager loading classique, voici ce qui nous a vraiment sauvé :
1. Lazy Eager Loading avec loadMissing() Quand tu récupères tes données par étapes, utilise `$orders->loadMissing('items.product')` plutôt que de refaire du with(). Ça évite de recharger ce qui est déjà en mémoire.
2. Query scopes avec des subqueries Pour les stats type "nombre d'items par commande", plutôt que de boucler côté PHP : ```php $orders = Order::withCount('items') ->addSelect(['latest_item_name' => OrderItem::select('name') ->whereColumn('order_id', 'orders.id') ->latest() ->limit(1) ])->get(); ```
3. Cache de requêtes avec remember() Si tu utilises pas encore spatie/laravel-query-builder avec le cache, c'est un game changer pour les listes produits qui bougent peu.
Qu'est-ce que tu utilises comme monitoring ? Laravel Telescope en dev c'est bien mais en prod, Blackfire ou New Relic te donneront des insights plus précis sur les vraies bottlenecks.
Tu as testé les index composites sur tes foreign keys ? Souvent oublié mais ça peut diviser par 10 le temps d'exec sur les gros volumes.
Dans ton cas avec 100k users actifs, je recommande fortement de mettre en place du monitoring en temps réel avant tout. Laravel Telescope c'est bien pour le dev, mais en prod tu as besoin de quelque chose de plus costaud.
Personnellement j'utilise Laravel Debugbar + New Relic pour traquer les requêtes lentes. Ça m'a sauvé la mise plusieurs fois sur des apps e-commerce similaires.
Pour ton problème spécifique User -> Orders -> OrderItems -> Products, as-tu pensé à dénormaliser certaines données ? Par exemple stocker directement le nom du produit et son prix dans order_items au lieu de faire systématiquement la jointure. Oui c'est moins "clean" mais en prod avec ce volume, ça peut diviser tes temps de réponse par 3.
Autre truc : pagination intelligente. Au lieu de charger toutes les commandes d'un user, limite à 20-50 par défaut avec un système de lazy loading.
Et si tu peux, jette un œil à Laravel Octane avec Swoole ou RoadRunner. Sur mes derniers projets ça a donné des gains de perf impressionnants sans changer le code métier.
Tu as testé avec combien de requêtes tu passes actuellement sur une page type ?
"La premature optimization is the root of all evil" - Knuth