# NgRx Signal Store vs. klassisches NgRx 2026: Welche Lösung passt zu Ihrem Projekt? > Vergleich zwischen NgRx Signal Store und klassischem NgRx Store im Jahr 2026. Architektur, Performance, Boilerplate-Code und Migrationsstrategien für Angular State Management. - Published: 2026-07-11 - Updated: 2026-07-11 - Author: SharpSkill - Reading time: 5 min --- Der NgRx Signal Store stellt einen grundlegenden Paradigmenwechsel im Angular State Management dar. Er ersetzt das traditionelle Redux-inspirierte Pattern aus Actions, Reducern und Selektoren durch einen signalbasierten reaktiven Ansatz. Dieser Vergleich untersucht beide Lösungen, um Angular-Entwicklern fundierte architektonische Entscheidungen im Jahr 2026 zu ermöglichen. > **Schnelle Entscheidungshilfe** > > Der **Signal Store** eignet sich für Feature-Level State und mittelkomplexe Anwendungen, bei denen Boilerplate-Reduzierung wichtig ist. **Klassisches NgRx** empfiehlt sich für Enterprise-Anwendungen mit strengen Audit-Anforderungen, komplexen Side Effects und umfangreichem DevTools-Debugging. ## Architektonische Unterschiede verstehen Klassisches NgRx folgt dem [Redux-Pattern](https://redux.js.org/understanding/thinking-in-redux/three-principles): Actions beschreiben Ereignisse, Reducer erzeugen neuen immutablen State, und Selektoren extrahieren Daten. Jede State-Änderung durchläuft eine vorhersagbare, nachvollziehbare Pipeline. Der Signal Store verfolgt einen anderen Ansatz. Anstatt Actions durch Reducer zu dispatchen, lebt der State in reaktiven Signals. Updates erfolgen durch Methoden, die `patchState()` aufrufen, und abgeleitete Werte stammen aus Computed Signals statt aus memoiserten Selektoren. | Aspekt | Klassisches NgRx | Signal Store | |--------|------------------|---------------| | Mentales Modell | Redux/Flux | Reaktive Services | | Boilerplate | Hoch (Actions, Reducer, Selektoren, Effects) | Niedrig (State, Methoden, Computed) | | Reaktivität | RxJS Observables | Angular Signals | | DevTools | Vollständige Redux DevTools | Signal Store DevTools (via Plugin) | | Lernkurve | Steil | Moderat | | Bundle-Größe | Größer | Kleiner | Für Entwickler, die bereits mit [Angular Signals](/technologies/angular/interview-questions/angular-signals) vertraut sind, fühlt sich der Signal Store wie eine natürliche Erweiterung der reaktiven Framework-Primitive an. ## Klassisches NgRx: Das Redux Pattern in Angular Klassisches NgRx organisiert das State Management rund um Actions, Reducer, Selektoren und Effects. Diese Trennung erzwingt Vorhersagbarkeit auf Kosten von Ausführlichkeit. ```typescript // books.actions.ts import { createActionGroup, emptyProps, props } from '@ngrx/store'; import { Book } from './book.model'; export const BooksActions = createActionGroup({ source: 'Books', events: { 'Load Books': emptyProps(), 'Load Books Success': props<{ books: Book[] }>(), 'Load Books Failure': props<{ error: string }>(), 'Add Book': props<{ book: Book }>(), 'Remove Book': props<{ id: string }>(), }, }); ``` Die `createActionGroup`-API gruppiert zusammengehörige Actions unter einer einzigen Quelle und verbessert die DevTools-Lesbarkeit. Im Vergleich zu individuellen `createAction`-Aufrufen reduziert sich der Boilerplate-Code erheblich. ```typescript // books.reducer.ts import { createReducer, on } from '@ngrx/store'; import { BooksActions } from './books.actions'; import { Book } from './book.model'; export interface BooksState { books: Book[]; loading: boolean; error: string | null; } const initialState: BooksState = { books: [], loading: false, error: null, }; export const booksReducer = createReducer( initialState, on(BooksActions.loadBooks, (state) => ({ ...state, loading: true, error: null, })), on(BooksActions.loadBooksSuccess, (state, { books }) => ({ ...state, books, loading: false, })), on(BooksActions.loadBooksFailure, (state, { error }) => ({ ...state, loading: false, error, })) ); ``` Reducer bleiben pure Funktionen, die neue State-Objekte zurückgeben. Die `on()`-Funktion übernimmt das Action-Matching und die State-Updates prägnant. ```typescript // books.selectors.ts import { createFeatureSelector, createSelector } from '@ngrx/store'; import { BooksState } from './books.reducer'; export const selectBooksState = createFeatureSelector('books'); export const selectAllBooks = createSelector( selectBooksState, (state) => state.books ); export const selectBooksLoading = createSelector( selectBooksState, (state) => state.loading ); export const selectPublishedBooks = createSelector( selectAllBooks, (books) => books.filter((book) => book.published) ); ``` Selektoren bieten automatische Memoisation. Der `selectPublishedBooks`-Selektor berechnet nur dann neu, wenn sich das Books-Array ändert, was Lesezugriffe auch bei häufig aktualisierten Stores effizient macht. ## NgRx Signal Store: Signals-First State Management Der Signal Store konsolidiert State, Computed Values und Methoden in einem einzigen injizierbaren Service. Die [offizielle NgRx-Dokumentation](https://ngrx.io/guide/signals/signal-store) beschreibt ihn als eine "vollständig ausgestattete State-Management-Lösung mit nativer Unterstützung für Angular Signals". ```typescript // books.store.ts import { computed, inject } from '@angular/core'; import { patchState, signalStore, withComputed, withMethods, withState } from '@ngrx/signals'; import { BooksService } from './books.service'; import { Book } from './book.model'; interface BooksState { books: Book[]; loading: boolean; error: string | null; } const initialState: BooksState = { books: [], loading: false, error: null, }; export const BooksStore = signalStore( { providedIn: 'root' }, withState(initialState), withComputed(({ books }) => ({ publishedBooks: computed(() => books().filter((book) => book.published)), totalBooks: computed(() => books().length), })), withMethods((store, booksService = inject(BooksService)) => ({ async loadBooks() { patchState(store, { loading: true, error: null }); try { const books = await booksService.getAll(); patchState(store, { books, loading: false }); } catch (error) { patchState(store, { loading: false, error: 'Failed to load books' }); } }, addBook(book: Book) { patchState(store, ({ books }) => ({ books: [...books, book] })); }, removeBook(id: string) { patchState(store, ({ books }) => ({ books: books.filter((book) => book.id !== id), })); }, })) ); ``` Das gesamte State Management eines Features passt in eine einzige Datei. State-Properties werden automatisch zu Signals, Computed Signals ersetzen Selektoren, und Methoden ersetzen das Action-Dispatching. ## Entity Management mit withEntities Beide Ansätze unterstützen Entity-Collections, aber das `withEntities`-Feature des Signal Store reduziert den Code dramatisch. ```typescript // books-entity.store.ts import { computed, inject } from '@angular/core'; import { patchState, signalStore, withComputed, withMethods } from '@ngrx/signals'; import { addEntity, removeEntity, setAllEntities, updateEntity, withEntities, } from '@ngrx/signals/entities'; import { BooksService } from './books.service'; import { Book } from './book.model'; export const BooksEntityStore = signalStore( { providedIn: 'root' }, withEntities(), withComputed(({ entities }) => ({ publishedBooks: computed(() => entities().filter((book) => book.published)), })), withMethods((store, booksService = inject(BooksService)) => ({ async loadBooks() { const books = await booksService.getAll(); patchState(store, setAllEntities(books)); }, addBook(book: Book) { patchState(store, addEntity(book)); }, updateBook(id: string, changes: Partial) { patchState(store, updateEntity({ id, changes })); }, removeBook(id: string) { patchState(store, removeEntity(id)); }, })) ); ``` Das `withEntities`-Feature stellt automatisch `ids`, `entityMap` und `entities` Signals bereit. Entity-Updater wie `addEntity`, `removeEntity` und `updateEntity` übernehmen die Collection-Mutationen. ## Custom Store Features für Wiederverwendbarkeit Die `signalStoreFeature`-Funktion des Signal Store ermöglicht es, querschnittliche Belange zu extrahieren und über Stores hinweg wiederzuverwenden. ```typescript // with-request-status.ts import { computed } from '@angular/core'; import { signalStoreFeature, withComputed, withState } from '@ngrx/signals'; type RequestStatus = 'idle' | 'pending' | 'fulfilled' | 'error'; export function withRequestStatus() { return signalStoreFeature( withState<{ requestStatus: RequestStatus }>({ requestStatus: 'idle' }), withComputed(({ requestStatus }) => ({ isPending: computed(() => requestStatus() === 'pending'), isFulfilled: computed(() => requestStatus() === 'fulfilled'), isError: computed(() => requestStatus() === 'error'), })) ); } export function setPending(): { requestStatus: RequestStatus } { return { requestStatus: 'pending' }; } export function setFulfilled(): { requestStatus: RequestStatus } { return { requestStatus: 'fulfilled' }; } export function setError(): { requestStatus: RequestStatus } { return { requestStatus: 'error' }; } ``` Dieses Custom Feature kann nun in jeden Store komponiert werden, der Loading-State-Tracking benötigt. ```typescript // books-with-status.store.ts import { inject } from '@angular/core'; import { patchState, signalStore, withMethods } from '@ngrx/signals'; import { setAllEntities, withEntities } from '@ngrx/signals/entities'; import { withRequestStatus, setFulfilled, setPending, setError } from './with-request-status'; import { BooksService } from './books.service'; import { Book } from './book.model'; export const BooksStore = signalStore( { providedIn: 'root' }, withEntities(), withRequestStatus(), withMethods((store, booksService = inject(BooksService)) => ({ async loadBooks() { patchState(store, setPending()); try { const books = await booksService.getAll(); patchState(store, setAllEntities(books), setFulfilled()); } catch { patchState(store, setError()); } }, })) ); ``` Der komponierte Store stellt nun `isPending()`, `isFulfilled()` und `isError()` Computed Signals bereit, ohne Logik zu duplizieren. ## Component Integration Patterns Der Signal Store integriert sich natürlich mit Angulars Template-Syntax durch Signal-Reads. ```typescript // books-list.component.ts import { Component, inject } from '@angular/core'; import { BooksStore } from './books.store'; @Component({ selector: 'app-books-list', standalone: true, template: ` @if (store.isPending()) {
Loading books...
} @if (store.isError()) {
Failed to load books
} @for (book of store.entities(); track book.id) {

{{ book.title }}

{{ book.author }}

}

Total: {{ store.totalBooks() }} books

`, }) export class BooksListComponent { readonly store = inject(BooksStore); constructor() { this.store.loadBooks(); } } ``` Kein Subscription-Management erforderlich. Keine Async Pipes. Signals integrieren sich mit Angulars [zoneless Change Detection](/blog/angular/angular-19-zoneless-change-detection-performance) für optimale Performance. ## Performance und Bundle-Größe Die leichtere Architektur des Signal Store führt zu kleineren Bundles. Das Core-Paket `@ngrx/signals` fügt etwa 4KB gzipped hinzu, verglichen mit 15-20KB für den vollständigen klassischen NgRx-Stack (`@ngrx/store`, `@ngrx/effects`, `@ngrx/entity`). Der Signal Store profitiert außerdem von Angulars signalbasierter Change Detection. Computed Signals berechnen nur neu, wenn sich Abhängigkeiten ändern, und Components rendern nur neu, wenn sich konsumierte Signals aktualisieren. Diese granulare Reaktivität eliminiert unnötige Change-Detection-Zyklen, die in Observable-basierten Patterns üblich sind. Für Anwendungen, die [RxJS bereits intensiv nutzen](/blog/angular/rxjs-angular-operators-subjects-signals-interop), integrieren sich die Observable-basierten Selektoren von klassischem NgRx nahtlos mit bestehenden Pipelines. ## Migrationsstrategie von klassischem zu Signal Store Die Migration einer bestehenden klassischen NgRx-Anwendung erfordert keinen Big-Bang-Rewrite. Beide Lösungen können koexistieren und ermöglichen eine inkrementelle Adoption. - Starten mit neuen Features unter Verwendung des Signal Store - Migration isolierter Feature-Module einzeln - Komplexe, stark effect-lastige Features auf klassischem NgRx belassen, wenn die Migrationskosten den Nutzen übersteigen - [NgRx Signals Interop](https://ngrx.io/guide/signals)-Utilities zur Brückenbildung zwischen Observable-basiertem und signalbasiertem State nutzen > **Koexistenz funktioniert** > > Klassischer NgRx Store und Signal Store können parallel in derselben Anwendung laufen. Das NgRx-Team unterstützt offiziell beide Ansätze und stellt Interop-Utilities zur Brückenbildung bereit. ## Wann welchen Ansatz wählen ### Signal Store empfiehlt sich wenn: - Neue Angular 20+ Anwendungen entwickelt werden - Feature-Level oder Component-Level State verwaltet wird - Developer Experience und reduzierter Boilerplate Priorität haben - Das Team begrenzte NgRx-Erfahrung hat - Bundle-Größe wichtig ist ### Klassisches NgRx empfiehlt sich wenn: - Bestehende NgRx-Anwendungen gewartet werden - Strenge Action-Protokollierung und Audit-Trails erforderlich sind - Komplexe Workflows mit umfangreichen Side Effects gebaut werden - Vollständiges Redux DevTools Time-Travel-Debugging benötigt wird - Das Team tiefgehende NgRx-Expertise besitzt Für [State Management Grundlagen](/technologies/angular/interview-questions/state-management-basics) bereitet das Verständnis beider Ansätze Entwickler auf diverse Angular-Codebasen vor. ## Fazit - Signal Store reduziert State-Management-Boilerplate um 60-70% im Vergleich zu klassischem NgRx - Klassisches NgRx bleibt die bessere Wahl für Enterprise-Anwendungen mit strengen Audit-Anforderungen und komplexen Side Effects - Beide Ansätze können in derselben Anwendung koexistieren und ermöglichen inkrementelle Migration - Computed Signals des Signal Store bieten automatische Memoisation ohne explizite Selektor-Definitionen - Custom Store Features (`signalStoreFeature`) ermöglichen wiederverwendbare querschnittliche Belange - Für neue Angular 20+ Projekte in 2026 sollte Signal Store die Standardwahl sein, es sei denn, spezifische Anforderungen erfordern klassisches NgRx --- Source: SharpSkill (https://sharpskill.dev), tech interview preparation for your real stack. HTML version of this page: https://sharpskill.dev/de/blog/angular/ngrx-signal-store-vs-classic-ngrx-comparison