The NGRX Signal Store offers a contemporary, compact approach to state management. Yet, integrating it into your application raises several architectural considerations: Where should it reside? What is the appropriate size? Can one store reference another? Is it suitable for global state? Can it complement or replace the conventional Redux-based NGRX Store?
This article addresses these questions and demonstrates that lightweight stores alter some of the conventions familiar from Redux-centric stores.
Placement Considerations
Drawing from Strategic Design (DDD) and Nrwl's contributions to Nx, our reference architecture partitions a large frontend into multiple decoupled domains (bounded contexts), each composed of several technical layers:

This architecture, which frequently serves as a baseline and can be adapted to specific needs, is detailed here.
With the traditional Redux-based NGRX Store, state is divided into feature slices. Although these could reside in the feature layer, they are often placed in the domain layer, since the same state is commonly required across multiple features within a single domain.
When discussing this reference architecture, it's worth noting that variations exist. For instance, some teams introduce a data or state layer to house feature slices shared by multiple features. These layers can serve as alternatives or as supplements to the domain layer.
Incorporating a lightweight store like the NGRX Signal Store introduces different guidelines: Generally, lightweight stores can be located in any technical layer:

- Feature Layer: A store can manage component-level state or feature-level state accessible to multiple components within the same feature. A wizard delegating to various components illustrates the latter scenario.
- UI: UI components inherently possess state. Some have substantial state that must be shared with child components, such as a complex scheduler with multiple views requiring several child components. A lightweight store bound directly to the component can manage this state.
- Domain: State needed across multiple features within a domain is defined here. A lightweight store for this purpose is exposed by the domain layer for the feature layer to use.
- Util: Utilities are often stateless—for instance, functions that validate inputs or compute dates. However, some stateful utility libraries benefit from a store, such as a generic authentication library tracking the current user or a translation library maintaining translation texts.
A store at the component level is provided directly by that component:
@Component({
[...],
providers: [MySignalStore]
})
export class MyComp {
[...]
}
This makes the store accessible to child components, but it also means the store is disposed of when the parent component is destroyed.
For other scenarios, the store can be provided via the root injector:
export const MySignalStore = signalStore(
{ providedIn: 'root'},
withState([...]),
[...]
)
The Angular team has repeatedly advised this as the standard approach. In theory, stores could be provided at the level of lazy-loaded routes. However, this yields little benefit because services in already function with lazy loading: if a service is only used in a lazy-loaded section, the bundler includes it in the corresponding chunk. For more details on route-level environment providers, refer to this resource.forRoot
Blending the Signal Store with the Classic NGRX Store
One might ask why not simply rely on the traditional NGRX Store for feature and domain state. That's entirely feasible: this store was designed for global state in those layers and fully supports Signals. Moreover, if you already use the traditional NGRX Store successfully, there's little reason to switch.
Still, I anticipate a growing number of developers questioning the "Redux by default" mindset. When the strengths of that pattern don't apply to your situation, a lighter alternative like the NGRX Signal Store becomes attractive. This trend is visible in other ecosystems where lightweight stores have long been favored.
To clarify, the Redux pattern remains a valuable tool. Yet, if a more lightweight solution fits your needs better, feel free to adopt it.
More: Angular Architecture Workshop (online, interactive, advanced)
Enhance your skills for enterprise-scale, maintainable Angular applications with our Angular Architecture workshop!
All Details (English Workshop) | All Details (German Workshop)
Optimal Combination via Custom Features
Given the NGRX Signal Store's high extensibility, you can integrate the best of both paradigms. Suppose you value the indirection or eventing inherent in Redux: nothing stops you from crafting a custom feature to incorporate that into the Signal Store. Resources on building generic, reusable custom features are available here.
Determining the Right Size for a Signal Store
For those transitioning from the traditional NGRX Store, a Signal Store can reasonably match the granularity of a feature slice. However, since a Signal Store is essentially a service, the single responsibility principle should guide its design. Therefore, dividing a feature slice into more granular stores can be advantageous.
Can a Signal Store Reference Other Signal Stores?
When state is distributed across multiple lightweight stores in different layers, a use case might require data from several stores. Generally, I'd advise against stores accessing one another. Each store should concentrate solely on managing its own state properties, and cycles should be avoided.
Fortunately, an alternative exists: a feature service coordinating the stores:

This service resembles the facades used in state management, but since it resides within a feature and doesn't abstract an external subsystem, I prefer the term feature service.
Avoiding Cycles, Duplication, and Inconsistencies
The layering of our reference architecture, combined with the rule that stores cannot call each other, prevents cycles. In general, our various stores risk becoming redundant and inconsistent if left unchecked. Yet, the same hazard exists with independent feature slices in the traditional NGRX Store.
Having a means to visualize state seems essential in both scenarios, aiding early detection of such problems. For the traditional NGRX Store, Redux Dev Tools serve this purpose. The Signal Store, however, lacks built-in support for them. Angular Dev Tools might eventually offer general visualization for Signals. Still, Redux Dev Tools support is exceptionally useful because it provides a history and enables time-travel debugging. Implementing such support via custom features should be manageable, and it's plausible the community will deliver such an integration, as seen with the NGRX Component Store.
Another strategy to prevent inconsistencies is leveraging eventing. This allows notifying other parts of the system about changes so they can update their state. In Redux, eventing is inherent. For the Signal Store, eventing can be introduced via custom features.
Final Thoughts
Lightweight stores such as the NGRX Signal Store shift some of the rules associated with Redux-based stores: they can be placed across various technical layers and provided through the root injector, a lazy route, or at the component level.
Redux remains a relevant tool in our toolbox. However, if a lighter solution better matches your needs, the NGRX Signal Store is an appealing option. You can also achieve the best of both worlds by combining the two stores or enhancing the Signal Store with custom features that supply missing Redux capabilities.
Adhering to the single responsibility principle, I'd advise against lightweight stores referencing one another; instead, introduce a feature service to orchestrate the required stores.
Up Next: More on Architecture!
Discover further insights on enterprise-scale Angular architectures in our free eBook (5th edition, 12 chapters):
- What criteria help divide a large application into sub-domains?
- How can we ensure long-term maintainability over years or even decades?
- What Micro Frontend options does Module Federation offer?
Feel free to download it here now!

