← Retour au blog
state-managementangularngrxsignalsarchitecture

State management : quand NE PAS utiliser NgRx (et ce qu'il faut choisir à la place)

NgRx est devenu une sorte de réflexe dans les équipes Angular ambitieuses. Dès qu'une application dépasse quelques écrans, on entend « il faudrait NgRx ». Pourtant, c'est une erreur stratégique. NgRx résout un problème très spécifique : gérer un état global complexe avec des actions synchrones et asynchrones, traçabilité complète, et middleware personnalisé. Si votre application n'a pas ces contraintes, NgRx devient une surcharge de boilerplate et une friction inutile pour votre équipe. Le coût cognitif de NgRx—actions, reducers, effects, selectors, et toute la philosophie Redux—n'est justifié que si vous en tirez un bénéfice réel.

Quand NgRx devient un poids mort

Voici les signaux d'alerte : votre état global tient en quelques variables simples (utilisateur connecté, thème, langue, notifications). Vous n'avez pas besoin de traçabilité temporelle ou de rejouer les actions. Votre logique métier n'implique pas de flux complexes d'appels API dépendants ou parallèles. Votre équipe est petite et a peu d'expérience Redux. Vous développez une MVP ou un prototype qui doit livrer vite. Dans tous ces cas, NgRx est un overhead. Vous passez 30 % de votre temps à écrire du boilerplate Redux au lieu de résoudre des vrais problèmes métier. Les actions deviennent des énumérations infinies. Les reducers se remplissent de cas par défaut verbeux. Et les tests NgRx demandent une infrastructure complexe avec MockStore, provideMockStore, etc. Le vrai danger : vous finissez par faire du NgRx « au doigt mouillé » sans vraie discipline, ce qui génère du code plus confus qu'une simple architecture service-signal.

L'alternative légère : services + Signals

Le duo services + Signals (les nouveaux Signals d'Angular 17+) couvre 95 % des cas d'usage quotidiens. Un service exposant des signaux permet un état réactif, traçable et testable sans framework lourd. Exemple concret : un service panier e-commerce. Vous créez un CartService avec un signal interne pour les items et des méthodes publiques pour ajouter, supprimer, vider. Les composants accèdent au signal via cartService.items(). Quand un item change, Angular déclenche l'effet automatiquement via les computed ou effects. Pas d'action, pas de reducer, pas de selector. Juste du TypeScript lisible.

const cart = signal<CartItem[]>([]); const total = computed(() => cart().reduce((sum, item) => sum + item.price * item.quantity, 0));

addItem(item: CartItem) { cart.update(items => [...items, item]); effect(() => console.log('Total mis à jour:', total())); }

Ce pattern est suffisant pour 80 % des applications Angular modernes. L'avantage : zéro boilerplate, debugging trivial (les signaux sont inspectables dans Angular DevTools), et l'état reste testable avec un simple spy. Vous pouvez même combiner plusieurs services en les injectant les uns dans les autres si vous avez besoin de coordination. Et contrairement à NgRx, les Signals jouent nativement avec le système de réactivité d'Angular, sans couche d'abstraction supplémentaire.

Quand NgRx devient justifié

Si vous avez une application financière avec des transactions concurrentes, une plateforme temps réel avec WebSocket et plusieurs flux de données asynchrones, ou un dashboard complexe où des actions utilisateur doivent déclencher des effets secondaires en cascade, NgRx commence à faire sens. Vous avez aussi besoin de NgRx si votre équipe exige une traçabilité complète de toutes les mutations d'état pour des raisons de compliance ou de débogage. Les DevTools NgRx permettent de rejouer chaque action, d'exporter l'historique, et de debugger des bugs timing qui seraient impossibles à reproduire autrement. Une autre justification : votre état global est vraiment énorme et fragmenté—plusieurs domaines d'état (user, products, orders, notifications) qui évoluent indépendamment mais doivent être synchronisés. Un store NgRx bien structuré avec plusieurs feature stores devient plus maintenable qu'une forêt de services.

Le piège courant : NgRx « par habitude »

Le piège le plus courant est d'adopter NgRx parce que l'équipe l'a utilisé avant, ou parce qu'on a peur qu'une future complexité nécessite NgRx. C'est du prédesign dangereux. Vous vous retrouvez avec un store NgRx de 500 lignes pour 3 actions simples. Les junior developers passent plus de temps à comprendre la structure NgRx qu'à résoudre des vrais bugs. Et quand la complexité arrive enfin, vous avez déjà du code NgRx maladroit qui pollue le reste. Le bon pattern : commencez par services + Signals. Si vous atteignez un point où vous vous dites « on a besoin de traçabilité d'actions », « on a trop de services qui communiquent », ou « on doit rejouer un flux », là vous migrez vers NgRx. Mais cette migration est souvent inutile. Mieux vaut un code simple et qui marche qu'un code complexe par anticipation.

Les vrais critères de décision

Posez-vous ces questions avant d'ajouter NgRx. Votre équipe maîtrise Redux et le pattern subscription ? Vous avez des actions asynchrones complexes avec gestion d'erreurs et retry ? Votre état global change à plus de 100 fois par seconde et vous devez optimiser les re-renders ? Vous avez des requirements de traçabilité ou d'audit ? Vous êtes plusieurs équipes travaillant sur le même store ? Si vous répondez oui à au moins deux, NgRx est probablement justifié. Si vous répondez non, services + Signals suffisent. Il n'y a pas de honte à ne pas utiliser NgRx. Les plus grandes applications Angular du monde utilisent un mix : NgRx pour le domaine critique (authentification, orders), services + Signals pour le reste (UI state, notifications, thème). C'est du pragmatisme d'architecture.

Conclusion : pragmatisme plutôt que dogme

State management n'est pas un sujet binaire. Il existe un spectre : Signals purs, services avec Signals, RxJS Subject/BehaviorSubject, Akita, NgRx. Choisir NgRx parce que c'est « professionnel » ou « scalable » est une erreur. Choisir NgRx parce que votre problème l'exige vraiment est une bonne décision. Commencez toujours par le plus simple. Vous pouvez refactoriser vers NgRx en 2-3 jours si vraiment nécessaire. Vous ne pouvez pas refactoriser hors de NgRx sans douleur si vous avez construit 10 000 lignes de code NgRx inutile. Pour 2026, la tendance est claire : les petites équipes abandonnent NgRx au profit de Signals + services, et les équipes matures le gardent seulement pour les domaines où il apporte vraiment de la valeur. Soyez honnête avec vous-même sur la complexité réelle de votre application. Votre futur vous remerciera.

Développeur Angular & Mobile freelance — Strasbourg.

© 2026 Emilien Pons — Tous droits réservés.Conçu avec Angular, PrimeNG et ❤️