Architecture
Angular Signals for State Management: Start Without a Store
Most Angular UI state does not need a store. Start with a local signal, promote it when the application actually shares it, and introduce a store only when the architecture earns one.

Most Angular UI state does not need a global store. A filter panel, expanded table row, selected tab or modal state often has exactly one consumer: the component rendering it. Moving that state into a service or store before another consumer exists adds architecture without solving a real sharing problem.
That is why I start Angular state management with the smallest primitive that solves the current problem: a local signal. State moves outward only when the application proves that it needs to be shared.
When Angular Signals are enough

Consider a filter panel whose open state is used by only one component. A service backed by a BehaviorSubject works, but it introduces another file, an observable, a subscription and teardown logic for a value that never leaves the component.
export class FilterPanelComponent {
readonly open = signal(false);
toggle(): void {
this.open.update((value) => !value);
}
}There is no subscription or teardown, and a developer reading the component can immediately see where the state originates. For component-specific UI state, that proximity is valuable.
The Angular state promotion rule

The rule I use is simple: promote state only when a second real consumer appears. Do not design around a consumer that might exist next quarter. Wait until another component actually needs the same state.
The progression then becomes predictable: start with a signal inside the component, move shared signals and computed values into a service when multiple consumers appear, and introduce a store when the state becomes genuinely application-wide or workflow-driven.
When to move Signals into a service
A service becomes useful when multiple components need the same source of truth. Derived state can then live beside the source state as computed signals instead of being recreated independently by every consumer.
@Injectable({ providedIn: 'root' }) export class CaseQueueState {
private readonly cases = signal<Case[]>([]);
readonly filter = signal<CaseFilter>('all');
readonly visibleCases = computed(() => {
const filter = this.filter(); return filter === 'all' ? this.cases() : this.cases().filter( (caseItem) => caseItem.status === filter );
});
load(cases: Case[]): void {
this.cases.set(cases);
}
}When Angular state actually needs a store
A store becomes more useful when state must survive navigation, multiple unrelated areas of the application can update it, complex workflows depend on predictable transitions, or the application benefits from centralized event-driven state management.
This is not an argument against NgRx or other Angular state-management libraries. They solve real problems. The important decision is whether the application currently has those problems.
Signals and zoneless Angular

Signals also fit naturally with zoneless Angular because state changes become explicit. Components depending on a signal can be notified when that signal changes instead of relying on broad asynchronous change-detection triggers.
bootstrapApplication(AppComponent, {
providers: [ provideZonelessChangeDetection(), ],
});The state-management test I use
Before introducing another state-management layer, I ask: who owns this state, who reads it, who writes it, and does it need to survive the component or route that created it?
If there is one owner and one consumer, a component signal is usually enough. If several components need it, promote it to a service. If unrelated parts of the application coordinate through it or the workflow requires centralized transitions, then a store has earned its place.
Starting small is easier to reverse than starting with unnecessary architecture. Angular Signals make that progression inexpensive, which is why local state is now my default rather than something I optimize toward later.
Keep reading
ArchitectureAngular Signal Forms: Building Custom Controls the Modern Way
Connect custom inputs, toggles, phone fields and rating controls to Angular Signal Forms with reusable validation schemas and clear ownership of form state.
ArchitectureI Stopped Writing Angular the Old Way: 10 Modern Angular Patterns I Use in 2026
The modern Angular patterns I use in 2026, why I use them, and when I would choose something else. A practical guide to clearer state, dependencies, forms, rendering and feature architecture.
