Angular Developer interview questions
100 real questions with model answers and explanations for Senior Angular Engineer candidates.
See a Angular Developer resume example →Practice with flashcards
Spaced repetition · Hunter Pass
Questions
I would split by business domain and expose one small public API from each domain.
- Each domain owns its routes, UI, data access, and state, while shared libraries contain only domain-neutral primitives.
- Imports cross domains through typed contracts or application orchestration, never through internal component or store paths.
- Nx dependency rules enforce domain and layer tags so an invalid edge fails in CI.
Why interviewers ask this: The interviewer is checking whether the candidate can turn domain ownership into enforceable dependency direction.
I would use standalone components by default and keep NgModules only at a proven compatibility boundary.
- Each component imports the directives, pipes, and components its template uses, which keeps dependencies local and statically visible.
- Application capabilities are composed at bootstrap with providers such as provideRouter and provideHttpClient rather than an AppModule.
- Feature boundaries still come from routes, libraries, and public APIs, because standalone does not define architecture by itself.
Why interviewers ask this: A strong answer treats standalone as the modern composition default without confusing it with domain architecture.
I would register analytics in the application EnvironmentInjector and checkout state on the checkout shell's ElementInjector.
- bootstrapApplication receives the global environment provider, giving every route one analytics adapter instance.
- The checkout shell component provides its state service, so each component instance creates one state instance and destroys it with the view.
- A route EnvironmentInjector is appropriate when child routes must share one feature service, but it should not be assumed to reset on every navigation.
Why interviewers ask this: The interviewer is evaluating provider placement through exact injector lifetime rather than a vague global-versus-local rule.
I would use @if so only the selected panel and its dependencies exist in the view.
- @if and @else express the exclusive branches directly without importing NgIf into a standalone component.
- Destroying the inactive branch also destroys its child views and subscriptions owned by those views instead of leaving hidden work running.
- State that must survive panel changes belongs above the conditional boundary, not inside a panel that is recreated.
Why interviewers ask this: The interviewer is checking whether the candidate understands the lifecycle consequences of built-in control flow.
I would track each row by an immutable order ID, not by object identity or $index.
- track order.id lets Angular move existing row views during sorting instead of destroying and recreating them.
- $index is safe only for a static list whose order and membership never change.
- Duplicate or mutable keys break identity, so the API contract must guarantee one stable ID per order.
Why interviewers ask this: A strong answer connects @for tracking to stable identity, DOM reuse, and correctness under reordering.
I would put transport translation behind a typed adapter at each route-family boundary.
- HttpClient adapters own URLs, generated DTOs, status mapping, and conversion into the shared Price contract.
- Components consume the domain model and never branch on API version or optional transport fields.
- Route providers select the correct adapter implementation through an InjectionToken without changing component code.
Why interviewers ask this: The interviewer is evaluating whether API volatility is contained at a concrete architectural boundary.
I would make each cohesive workflow a lazy route subtree and keep only the shell and first route eager.
- loadChildren or loadComponent preserves a dynamic import boundary around each workflow.
- Nested routes keep guards, resolvers, and providers close to the workflow they coordinate.
- A shared library may hold stable primitives, but importing a lazy feature from the shell would collapse the split.
Why interviewers ask this: The interviewer is checking route composition, lazy boundaries, and protection against accidental eager imports.
I would publish one focused summary component with explicit extension points for the four action areas.
- Typed inputs carry customer data, outputs report domain-neutral user intent, and projected content supplies optional actions.
- The shared component owns layout and accessibility, while product policy stays in each consuming feature.
- I would reject a growing matrix of boolean inputs because combinations become an undocumented second product model.
Why interviewers ask this: The interviewer is evaluating reuse through stable contracts rather than duplication or flag-heavy components.
I would keep only user-owned inputs writable and derive tax and total with computed.
- Quantity, price, discount, and tax jurisdiction are writable signals because user actions replace those values.
- computed memoizes the total and reruns only when a signal read on its latest execution changes.
- Persisting the calculated total separately would create two writable sources that can disagree.
Why interviewers ask this: The interviewer is checking whether the candidate distinguishes source state from derived signal state.
I would derive the cart total with computed and reserve an effect for the imperative chart synchronization.
- The template reads the computed value directly, so Angular tracks that dependency without an effect writing more state.
- The effect calls the chart API and registers cleanup if the chart library keeps resources or listeners.
- Using an effect to copy one signal into another introduces timing and write-loop risks that computed avoids.
Why interviewers ask this: A strong answer uses effect only at an imperative boundary and keeps derivation declarative.
I would read accountId normally and read locale with untracked inside the effect.
- The tracked accountId read reruns the effect when the selected account changes.
- untracked(() => locale()) captures the current locale without adding it to the dependency graph.
- I would not use untracked to hide a real dependency, because that would leave synchronized output stale.
Why interviewers ask this: The interviewer is evaluating precise control of dynamic signal dependencies rather than indiscriminate use of untracked.
I would expose a required signal input for the dataset and a transformed signal input for precision.
- input.required<Dataset>() makes omission a template type error and gives internal code a Signal<Dataset>.
- An input transform converts the attribute string to a bounded number at the component boundary whenever the binding updates.
- Internal computed values derive chart series from those inputs without copying them in ngOnChanges.
Why interviewers ask this: The interviewer is checking current signal input contracts, coercion, and derived state design.
I would expose model<DateRange>() when two-way binding is an intentional part of the component contract.
- Calling range.set or range.update changes local state and emits the corresponding rangeChange event to the parent.
- A read-only value should remain input(), because model grants the child write authority over the binding.
- Form validation and touched state still need the Angular forms contract if this component acts as a form control.
Why interviewers ask this: The interviewer is evaluating when model inputs express genuine shared ownership and when they overexpose mutation.
I would update it through Angular-recognized notifications rather than mutating an unobserved field.
- A changed input through Angular, a bound template or host listener, and ComponentRef.setInput can notify the view.
- A template-read signal update, AsyncPipe emission, or ChangeDetectorRef.markForCheck also schedules checking.
- Mutating the existing input object inside an arbitrary callback preserves its reference and provides no reliable notification.
Why interviewers ask this: The interviewer is checking exact OnPush notification semantics instead of the myth that only input changes matter.
I would bootstrap with provideZonelessChangeDetection() and remove Zone.js from the application polyfills.
- Signal writes read by templates, AsyncPipe emissions, bound listeners, setInput, and markForCheck provide recognized notifications.
- Third-party callbacks are wrapped at one adapter boundary that writes a signal or marks the owning view.
- Tests await their actual async operation or rendered state instead of relying on Zone.js stabilization.
Why interviewers ask this: A strong answer treats zoneless mode as an explicit notification model, not a performance flag.
I would remove the late mutation and make the title stable before Angular verifies the completed check.
- The error means a binding produced one value during checking and another during the development verification pass.
- Input-derived titles belong in computed or earlier initialization, while user-driven changes belong in a later event handler.
- Calling detectChanges or hiding the write in a timer masks the ownership problem instead of fixing the data flow.
Why interviewers ask this: The interviewer is checking whether the candidate understands the invariant behind the error and fixes causality rather than suppressing it.
I would keep the current filters and derived UI state in signals and keep request timing in one RxJS pipeline.
- toObservable converts the filter signal once, then debounceTime and switchMap implement cancellation of stale requests.
- toSignal converts the resulting read model once for template consumption with an explicit initial state.
- Repeated conversion in individual components would create unclear subscription ownership and duplicate cold work.
Why interviewers ask this: The interviewer is evaluating a deliberate interop boundary that preserves both signal and stream semantics.
I would debounce the query and use switchMap because every new query supersedes the previous request.
- switchMap unsubscribes from the stale inner HttpClient Observable when a newer query arrives.
- distinctUntilChanged avoids requesting the same normalized query twice.
- The response updates only the latest query state, so a slow old response cannot overwrite a newer result.
Why interviewers ask this: The interviewer is checking whether cancellation policy follows the product's latest-result requirement.
I would use concatMap because no accepted revision may be cancelled or reordered.
- Each revision waits for the previous save Observable to complete before its request starts.
- The queue must be bounded by debouncing or snapshot coalescing if users can produce revisions faster than the API saves them.
- A failed inner save is handled inside the projection so one error does not permanently terminate later saves.
Why interviewers ask this: A strong answer chooses ordered queuing and also addresses the queue growth that concatMap can create.
I would use exhaustMap because the first click owns the authorization window and overlap must be ignored.
- While the inner request is active, exhaustMap drops later click emissions instead of cancelling or queuing them.
- The UI also disables the button for feedback, but operator semantics remain the correctness guard.
- The request still carries an idempotency key because client-side click suppression is not a payment guarantee.
Why interviewers ask this: The interviewer is evaluating precise overlap semantics and awareness that RxJS is not the backend correctness boundary.
Locked questions
- 21
An upload screen may send 100 files but the API allows only four concurrent uploads; which RxJS mapping policy would you implement?
rxjsapiconcurrency - 22
A route needs a current user value, a fire-and-forget refresh event, the last three validation messages, and one final export result; which Subject types fit?
rxjsvalidation - 23
A dashboard shell subscribes to a WebSocket and must close whenever that shell leaves the outlet; how would you bind teardown to Angular lifetime?
angularwebsockets - 24
A live search must continue after one HTTP 500; where would you place catchError relative to switchMap?
rxjshttp - 25
Six widgets consume one route-scoped pricing stream, and the upstream WebSocket should disconnect when the route has no subscribers; how would you share it?
pricingwebsockets - 26
A report page has a live filter, three one-shot startup requests, and a refresh button that needs the latest filter; which combination operators would you assign?
- 27
A telemetry view receives 5,000 events per second but may repaint at 60 frames per second and send batches every 100 ms; how would you control pressure?
renderingbatch - 28
A 20-domain Angular platform needs cross-domain commands traceable through actions, while a wizard's state dies on navigation; would you use classic NgRx Store or SignalStore for each?
angularstate-managementsignals - 29
A lazy claims route owns 200,000 normalized claims and no other route reads them; how would you register its NgRx feature?
state-managementnormalization - 30
An NgRx order effect handles 50 commands per second and needs the current account policy; what belongs in the action, and what would you read with concatLatestFrom?
state-management - 31
A dashboard recomputes a 50,000-row view model on unrelated actions; how would you redesign its NgRx selectors?
state-management - 32
Ten screens edit the same 300,000 customers by ID; would you store separate arrays per screen or use NgRx Entity?
state-management - 33
A route SignalStore needs the authenticated account from classic NgRx Store and adds local selection state; how would you prevent two sources of truth?
state-managementsignals - 34
A five-component pricing feature has local filters, server requests, and no cross-route consumers; would you introduce classic NgRx Store?
componentsstate-managementpricing - 35
A public Angular storefront has 2 million monthly visits; which exact Core Web Vitals targets would you make release criteria?
angularweb-vitals - 36
A customer portal has a 250 KB compressed shell and twelve 120 KB lazy routes; users usually open one of two routes next; what would you preload?
- 37
A below-the-fold reviews widget costs 180 KB and only 30 percent of visitors reach it; which @defer triggers would you choose?
- 38
A deferred recommendation panel is 420 px tall, and its placeholder currently collapses to 40 px before loading; how would you prevent layout shift?
web-vitals - 39
A site has 30,000 stable help pages, 2,000 fresh public product pages, and a private dashboard; which modern @angular/ssr render mode would you assign to each route family?
ssrangular - 40
A server-rendered article has an interactive poll below the fold, and users may click it before its code loads; how would you hydrate it?
- 41
An SSR account page makes three GET requests containing user data; how would you avoid duplicate browser requests without leaking one user's data to another?
ssr - 42
A server-rendered map route reads window during construction and its HTML differs by locale cookie; how would you make rendering deterministic?
htmlcookies - 43
An application provider and a component subtree both bind the same token; which instance should a directive inside that subtree receive?
componentsdirectivestokens - 44
Four payment plugins must register validators without importing each other; how would you model the DI contract and lifetime?
validation - 45
A library build passes TypeScript but a consumer template binds string to a number input; which Angular compilation stages should catch it?
angulartemplatestypescript - 46
A component library supports three Angular majors and consumers import only 20 of 200 components; how would you package it for compatibility and tree shaking?
componentsangulartree-shaking - 47
Five teams share one Angular repository, release weekly together, and have no independent deployment requirement; would you introduce Module Federation?
angularfederationdeployment - 48
A Module Federation host deploys monthly while three Angular remotes deploy daily; what version contract would you require for shared Angular packages?
angularfederationdeployment - 49
An Nx workspace has 60 Angular projects across billing, identity, and catalog; how would you prevent UI libraries from reaching another domain's data-access code?
angularmonorepo - 50
A 60-project Nx CI takes 45 minutes, but a typical change touches two libraries; how would you use affected execution and cache without stale results?
monorepocaching - 51
A trading screen jumps from 1,400 to 9,200 component checks per tick and INP rises from 180 to 480 ms; production must stay live while you diagnose it. What do you do?
components - 52
Angular DevTools reports a 95 ms check for one of 600 table rows, but Chrome Performance shows 260 ms in layout; you may change only the row component this sprint. How do you act?
componentsangularperformance - 53
After converting 80 tiles to OnPush, prices freeze for 7% of users while WebSocket messages still arrive at 20 per second; reverting all 80 tiles is forbidden. How do you fix it?
websockets - 54
A live grid with 12,000 rows drops from 55 to 18 fps after every 5-second sort because @for tracks by $index; DOM virtualization cannot ship this month. What do you change?
griddomindexes - 55
A checkout summary shows the old total for 1 frame after a 2,000 ms payment callback, and development reproduces ExpressionChangedAfterItHasBeenCheckedError; adding setTimeout is prohibited. How do you fix the flow?
callbacks - 56
Heap usage rises from 180 to 620 MB after 30 navigations between two routes, and each visit adds one RxJS subscriber; the shared API service must remain root-scoped. How do you find and fix the leak?
rxjsapidata-structures - 57
After opening and closing a modal 40 times, Chrome shows 40 detached dialog trees and heap grows by 96 MB; the overlay library cannot be replaced this release. How do you contain it?
data-structures - 58
A route service uses takeUntilDestroyed yet retains 25 editor components after 25 navigations because its DestroyRef comes from a cached route EnvironmentInjector; route reuse must stay enabled. What do you change?
componentsrxjscaching - 59
A 50 MB report remains retained 15 minutes after its last viewer closes because a root service uses shareReplay(1); new viewers still need one cached result for 60 seconds. How do you redesign it?
rxjscaching - 60
Each of 6 reconnects adds another WebSocket, so one quote arrives 7 times; the server permits only 1 connection per account and reconnect must stay automatic. How do you fix ownership?
ownershipwebsockets - 61
A release increases the compressed initial bundle from 310 to 690 KB and mobile LCP from 2.4 to 4.1 seconds; the new chart must remain available today. How do you respond?
- 62
A 90 KB utility import becomes 410 KB in the initial chunk and LCP worsens by 0.9 seconds; replacing the dependency is out of scope for 2 weeks. What do you inspect?
dependencies - 63
A lazy admin route adds 280 KB to the 420 KB initial bundle after one shared barrel change, and only 3% of sessions visit it; route URLs cannot change. How do you restore the split?
sessions - 64
An @defer analytics panel still ships inside the 760 KB initial chunk and adds 1.2 seconds to LCP; its trigger must remain on viewport. Why did splitting fail?
css - 65
A 240 KB reviews widget appears after 4 seconds and causes CLS 0.22 when @defer swaps a 48 px placeholder; you cannot load it eagerly. What do you change?
- 66
Zone.js schedules 1,100 ticks per minute on a dashboard although only 60 price updates affect the UI; a vendor timer firing every 50 ms cannot be removed. How do you reduce the work?
procurement - 67
After enabling provideZonelessChangeDetection for 10% of traffic, a map callback updates coordinates 8 times per second but the marker freezes; Zone.js cannot be restored globally. What do you patch?
callbacks - 68
A 140-route app gets 14% better INP in a zoneless pilot, but 9 of 70 third-party workflows miss updates; the release window is 3 weeks. Do you continue?
change-detectiondependencies - 69
Hydration mismatch rises from 0.1% to 6% on 24 SSR locales after a release that formats time and generates card IDs; disabling SSR is forbidden. How do you make the first render deterministic?
hydrationssr - 70
An SSR account page leaks one user's 3 API responses into another request under 200 requests per second; TransferState must still prevent duplicate browser fetches. How do you isolate it?
ssrapi - 71
An SSR product page is blank for 12% of mobile users because a constructor reads window and a chart writes directly to DOM before hydration; the chart must remain indexable. What do you change?
domhydrationssr - 72
An NgRx search effect sends 24 requests for 12 keystrokes and an old response overwrites the newest result; the API cannot be changed. Which race do you fix?
state-managementapi - 73
An autosave effect loses 3 of 10 edits because switchMap cancels saves, while the backend accepts only 1 write at a time and every revision must persist. What do you use?
rxjs - 74
The same 80,000 products exist in NgRx Entity and a feature SignalStore, doubling heap to 340 MB; 14 screens need local filters but one canonical price. How do you remove duplication?
state-managementsignalsdata-structures - 75
A selector for 60,000 orders runs 420 times during 1 filter change because consumers create selector factories in templates; component APIs cannot change this sprint. How do you restore memoization?
componentstemplatesapi - 76
An optimistic NgRx delete hides 1 of 500 invoices, the API returns 409, and the invoice never returns; refetching all 500 records is too expensive. How do you roll back?
state-managementapilocking - 77
An NgRx payment effect charges twice after 2 rapid clicks because mergeMap runs 2 requests; the UI must remain responsive and the API rollout is 6 weeks away. What do you change now?
responsivestate-managementrxjs - 78
One NgRx load action triggers 3 HTTP calls and 3 success actions after a feature is entered 4 times; effects are registered only once by policy. How do you locate the duplication?
state-managementhttp - 79
Three toSignal calls over one cold report stream produce 3 downloads of 18 MB each; 9 components under one route shell need the result and cancellation when that shell leaves must remain. How do you fix it?
componentsresilience - 80
An NgRx effect cached tenant ID when the feature opened, then a save action 500 ms after an account switch writes to the previous tenant; the action contract cannot grow this release. How do you remove the stale read?
state-managementcaching - 81
A migration must convert 120 routes from NgModules to standalone in 8 weeks, with at most 2 routes per rollback and no change to provider semantics. How do you sequence it?
modulesstandalone-componentsmigrations - 82
After converting 35 NgModules to standalone, checkout state survives 6 route reentries instead of resetting; rollback is limited to the last 5 modules. What semantic loss do you inspect?
modulesstandalone-componentsrollback - 83
You must migrate RxJS component state in 180 components to signals over 10 weeks, while preserving all cancellation and error semantics and limiting rollback to 10 components. How do you plan it?
componentsrxjssignals - 84
After migrating 20 search components to signals, stale HTTP results appear in 4 components because an effect replaced switchMap; the release cannot revert the other 16. How do you repair it?
componentssignalsrxjs - 85
A Module Federation remote on Angular 21 gives a blank route in a host on Angular 20 for 18% of sessions; remotes deploy daily and the host deploys monthly. How do you recover?
angularfederationdeployment - 86
A minified production build shows a blank screen for 3,200 users, but source maps are restricted to the error service and rollback would discard 2 unrelated fixes. How do you isolate the fault?
source-mapsbuildrollback - 87
Nx remote cache reports a hit after a tsconfig path change, but 11 Angular libraries use stale JavaScript and 6 tests pass incorrectly; disabling cache permanently is not allowed. What do you fix?
angularmonorepocaching - 88
Nx affected skips 9 Angular consumers after a generated OpenAPI schema changes, cutting CI from 28 to 9 minutes but shipping stale clients; the 9-minute target must remain. How do you repair the graph?
angularmonoreposchema - 89
After a design-system update, keyboard completion drops from 92% to 61% across 14 dialogs because focus escapes; reverting the other 7 fixes is prohibited. How do you handle the regression?
system-designdesignsoft-skills - 90
A zoneless migration makes 37 of 1,800 async tests flaky because they rely on fixture.whenStable(); production code cannot regain Zone.js. How do you migrate the tests?
flakyfixturesmigrations - 91
A mid-level engineer proposes memoizing all 260 components after INP reaches 360 ms, but Angular DevTools shows 8,400 checks from 1 parent signal; you have 2 pairing sessions before release. How do you mentor them?
componentsangularsignals - 92
A junior has caused 2 RxJS leaks in 6 weeks, and the latest retains 70 components after navigation; you may spend 3 hours mentoring without taking over the fix. What do you do?
componentsrxjsmentoring - 93
A pull request changes switchMap to mergeMap in 4 NgRx effects and tests still pass, but one slow response can overwrite a newer search; review must finish in 45 minutes. How do you handle it?
state-managementrxjssoft-skills - 94
An engineer is leading their first standalone migration across 16 routes, and the pilot accidentally promotes 3 providers to root; rollback must stay within 1 route. How do you coach the recovery?
standalone-componentsmigrationsrollback - 95
A reviewer approves a dialog that passes 24 unit tests but traps keyboard focus in only 2 of 5 close paths; release is in 1 day and visual redesign is forbidden. What do you ask them to fix?
unit - 96
A new test author uses setTimeout(500) in 18 async tests, causing 7% CI flakiness and adding 9 minutes; the feature must merge in 2 days. How do you mentor and unblock it?
mentoringasynctesting - 97
A pull request adds 330 KB to a 460 KB initial bundle and worsens lab LCP by 1.4 seconds, but the author says tree shaking will fix production; the route budget is 500 KB. What evidence do you require?
code-reviewtree-shaking - 98
A teammate fixes 11 hydration mismatches by wrapping random IDs in isPlatformBrowser, but SSR now renders empty cards for 4 seconds; the patch must keep SEO content. How do you review and teach the correction?
hydrationssr - 99
A production incident came from an eager import that pulled a 270 KB lazy feature into the shell, even though 6 reviewers approved it; you may add only 1 automated guard this quarter. Which one?
incidentsrouting - 100
Three incidents in 60 days came from wrong RxJS flattening operators in 12 effects, and the team can spend only 1 day on prevention without banning mergeMap. What do you implement?
rxjsincidents