Skip to content

MEAN Stack Interview Questions for 2 Years Experience

40 questions with answers for candidates with 2 years of experience — 11 easy, 29 medium.

What interviewers expect: 2 years experience

At two years, questions shift to reasoning and trade-offs. Expect RxJS flattening operators, subscription leaks, signals versus subjects, OnPush change detection, lazy loading and typed forms with FormArray. On the backend, expect indexing, aggregation and JWT refresh flows. You should describe a performance or async bug you solved and show that you write unit tests with TestBed.

This set is weighted towards Angular Components and Templates (8), Angular Forms and HTTP Client (7), MongoDB Data Modelling and Queries (7), Security, Testing and Deployment (5).

RxJS and signals Change detection MongoDB indexing Unit testing
Solved at this levelStart practicing
3 QUESTIONS FREESign up to unlock the full question bank and track your progress.Unlock every question and answer, then continue practising company-wise and package-wise.
3 questions free Unlock the rest in seconds
01

How do you set up an Express project with TypeScript?

Save to ▾
Show answer
Install express and types with npm i express and npm i -D typescript @types/express @types/node. Create a tsconfig with strict mode and a module setting like NodeNext, write code in src and compile to dist with tsc. For development, run TypeScript directly with tsx watch, and use node dist/server.js in production. Type request bodies, params and responses with Request and Response generics or validated schemas.
02

How should HTTP errors be handled in an Angular application?

Save to ▾
Show answer
Handle them at two levels. A global error interceptor catches HttpErrorResponse, redirects to login on 401, shows a toast for 500 errors and logs details. Component or service code uses catchError to provide fallbacks or show specific messages, such as field errors from a 422 response. Use retry with a delay for transient network failures, and never leave errors unhandled so the UI shows a blank state.
03

Write mongosh commands to inspect a slow query and the indexes on a collection.

Save to ▾
Show answer
Useful diagnostic commands: db.orders.getIndexes() db.orders.find({ status: 'pending', city: 'Pune' }) .sort({ createdAt: -1 }) .explain('executionStats') db.setProfilingLevel(1, { slowms: 100 }) db.system.profile.find().sort({ ts: -1 }).limit(5) db.orders.createIndex({ status: 1, city: 1, createdAt: -1 }) Compare totalDocsExamined with nReturned before and after creating the index.
04

Create a counter component with signal, computed and effect.

Save to ▾
Show answer
Signals keep simple state readable. import { Component, signal, computed, effect } from '@angular/core'; @Component({ selector: 'app-counter', template: ` <p>Count: {{ count() }} (double: {{ double() }})</p> <button (click)='increment()'>+</button> <button (click)='count.set(0)'>Reset</button> ` }) export class CounterComponent { count = signal(0); double = computed(() => this.count() * 2); constructor() { effect(() => console.log('count changed to', this.count())); } increment() { this.count.update((c) => c + 1); } }
05

What is HttpClient and how is it set up in a standalone Angular app?

Save to ▾
Show answer
HttpClient is Angular's service for making HTTP requests. It returns Observables, automatically parses JSON, supports typed responses with generics, interceptors, progress events and request cancellation by unsubscribing. In a standalone app you register it with provideHttpClient() in app.config.ts, optionally with withInterceptors([...]) and withFetch() to use the Fetch API, which is recommended for server-side rendering.
06

An npm audit shows several high-severity vulnerabilities in the Express project. How do you handle it?

Save to ▾
Show answer
Read each advisory to see whether the vulnerable code path is actually used in production or only in dev tooling. Run npm audit fix for safe updates, upgrade direct dependencies that pull vulnerable transitive packages, and use overrides in package.json if a fix is not yet released upstream. Test thoroughly after upgrading, enable Dependabot or Renovate for continuous updates and track any accepted risks.
07

How do you use Mongoose with TypeScript?

Save to ▾
Show answer
Define a TypeScript interface for the document, then create a Schema typed with that interface and a model with model<IUser>('User', userSchema). Mongoose infers types for queries, so findById returns a typed document. For lean queries, results are plain typed objects. Schema options like timestamps add createdAt and updatedAt, and you can type instance methods, statics and virtuals through additional generic parameters.
08

A product list with 2,000 rows re-renders slowly whenever any data changes. How do you optimise it?

Save to ▾
Show answer
Use @for with a proper track expression, such as track product._id, so Angular reuses DOM nodes instead of recreating them. Switch the component to OnPush and update data immutably or with signals. Replace function calls in templates with computed signals or pure pipes. For very long lists, use virtual scrolling from the Angular CDK and paginate on the server.
09

What is the difference between an interface and a type alias in TypeScript?

Save to ▾
Show answer
Both describe the shape of data. Interfaces are open, so declarations with the same name merge, and they can be extended with extends, which suits object models and class contracts. Type aliases can describe unions, intersections, tuples, primitives and mapped types, such as type Status = 'active' | 'blocked'. Many teams use interfaces for object shapes like API models and type aliases for unions and utility compositions.
10

Serve the built Angular app and the API from one Express server.

Save to ▾
Show answer
API first, static files next, fallback last. import express from 'express'; import path from 'node:path'; const app = express(); app.use(express.json()); app.use('/api', apiRouter); const dist = path.join(process.cwd(), 'dist/shop/browser'); app.use(express.static(dist, { maxAge: '1y', index: false })); app.get('/*splat', (req, res) => { res.sendFile(path.join(dist, 'index.html')); }); app.listen(process.env.PORT || 3000); The named wildcard follows Express 5 path syntax.
11

What is the role of a controller-service-repository structure in an Express API?

Save to ▾
Show answer
Controllers handle HTTP: they read request data, call services and format responses with status codes. Services contain business rules, such as checking stock before creating an order, and are independent of Express. Repositories or models encapsulate database access through Mongoose. This separation makes code easier to test, lets you reuse services in jobs or other transports, and stops route files from turning into large unmaintainable blocks.
12

How do containers and orchestration fit into deploying a MEAN stack?

Save to ▾
Show answer
Docker packages the Express API and an Nginx image serving the Angular build into portable images with all dependencies. docker compose runs them with MongoDB locally. In production, services like AWS ECS, Azure Container Apps or Kubernetes run multiple replicas, perform rolling updates, restart failed containers and scale on load. Images are built and pushed to a registry by the CI pipeline, tagged by commit.
13

What is an Angular component and what are its main parts?

Save to ▾
Show answer
A component controls a piece of the screen. It is a TypeScript class decorated with @Component, which provides a selector used as an HTML tag, a template or templateUrl for the view, styles or styleUrl for scoped CSS, and imports for other standalone components, directives and pipes it uses. The class holds data and event handlers, and the template binds to them.
14

Users double-click the Pay button and two payment requests are sent. How would you prevent it on the frontend?

Save to ▾
Show answer
Disable the button while the request is pending, using an isSubmitting signal. In RxJS, model clicks as a stream and use exhaustMap, which ignores new clicks until the current payment request completes. Show a loading state and handle errors so the button re-enables. The backend must still use idempotency keys, because frontend protection alone cannot stop network retries or duplicate tabs.
15

A component subscribes to a service Observable in ngOnInit, and after navigating back and forth several times, the API is called multiple times per action. What is wrong?

Save to ▾
Show answer
The subscriptions are never cleaned up, so each visit adds another live subscriber that reacts to every emission. Use the async pipe or toSignal in the template, or add takeUntilDestroyed() to manual subscriptions. Also check that the service does not create a new long-lived stream per call and that nested subscribes are replaced with switchMap. Angular DevTools and network logs confirm the fix.
16

What are Angular's lifecycle hooks and when is each typically used?

Save to ▾
Show answer
ngOnChanges runs when input values change. ngOnInit runs once after the first inputs are set, used for initial data loading. ngDoCheck allows custom change detection. ngAfterContentInit and ngAfterViewInit run after projected content and the view are ready, used for DOM access. ngOnDestroy runs before removal, used for cleanup. With signals, effect, computed and DestroyRef often replace several of these hooks.
17

Write an injectable service that fetches and caches a list of categories.

Save to ▾
Show answer
Cache the Observable with shareReplay so the API is called once. import { Injectable, inject } from '@angular/core'; import { HttpClient } from '@angular/common/http'; import { Observable, shareReplay } from 'rxjs'; export interface Category { _id: string; name: string } @Injectable({ providedIn: 'root' }) export class CategoryService { private http = inject(HttpClient); private categories$?: Observable<Category[]>; getAll(): Observable<Category[]> { this.categories$ ??= this.http.get<Category[]>('/api/categories') .pipe(shareReplay({ bufferSize: 1, refCount: false })); return this.categories$; } }
18

A dashboard needs data from three independent APIs before it can render. How would you load them?

Save to ▾
Show answer
Use forkJoin to run all three requests in parallel and emit once when all complete, giving an object or array of results. Handle errors per request with catchError returning a fallback value, so one failed widget does not block the whole dashboard. If any source emits repeatedly, use combineLatest instead. With signals, you could use three httpResource instances and a computed for the combined loading state.
19

Create a text index and run a relevance-sorted search in MongoDB.

Save to ▾
Show answer
Text search with scores: db.articles.createIndex({ title: 'text', body: 'text' }, { weights: { title: 5, body: 1 } }) db.articles.find( { $text: { $search: 'angular signals' } }, { score: { $meta: 'textScore' }, title: 1 } ).sort({ score: { $meta: 'textScore' } }).limit(10) Weights make title matches rank higher. A collection can have only one text index, so include all searchable fields in it.
20

Users can search products by name, and a regex query has become very slow. What would you do?

Save to ▾
Show answer
A regex without an anchored prefix cannot use a normal index efficiently and scans the collection. For simple word search, create a text index and use $text with a relevance score. For a better search experience with typo tolerance, autocomplete and facets, use Atlas Search or a dedicated search engine. Paginate results, limit fields with projection and debounce requests from the Angular search box.
21

You are building an e-commerce product catalogue where each category has different attributes, such as size for clothes and RAM for laptops. How would you model it in MongoDB?

Save to ▾
Show answer
Store common fields like name, price, category and stock at the top level, and keep variable specifications in an attributes array of { key, value } pairs, the attribute pattern. Create a compound index on attributes.key and attributes.value so filters work on any attribute. This avoids dozens of sparse fields and lets new categories be added without schema changes, while Mongoose validates the common fields.
22

What are standalone components and why are they now the default?

Save to ▾
Show answer
Standalone components declare their own dependencies in an imports array instead of belonging to an NgModule. Since Angular 19 they are the default, and the CLI generates them without NgModules. They reduce boilerplate, make lazy loading simpler with loadComponent, improve tree shaking and make components easier to understand and test. Applications bootstrap with bootstrapApplication and configure providers in app.config.ts.
23

Your app must call different API base URLs for development, staging and production. How do you configure this in Angular?

Save to ▾
Show answer
Use environment files such as environment.ts and environment.prod.ts with fileReplacements in angular.json build configurations, or load a config.json at startup with provideAppInitializer so one build works in every environment. Expose the URL through an InjectionToken and inject it in services or an interceptor. Never put secrets in these files, because everything in the Angular bundle is public.
24

After a new release, a bug affects many users. How do you respond and prevent a repeat?

Save to ▾
Show answer
First limit the impact: roll back to the previous version or disable the feature with a flag, and communicate status to support. Then reproduce the bug, fix it with a test that covers the case, and redeploy through the normal pipeline. Afterwards, run a blameless post-mortem to find gaps, such as missing tests, review or monitoring, and add the actions to the backlog.
25

What query and comparison operators do you use most in MongoDB?

Save to ▾
Show answer
Comparison operators include $eq, $ne, $gt, $gte, $lt, $lte, $in and $nin, for example { price: { $gte: 500, $lte: 2000 } }. Logical operators are $and, $or, $not and $nor. Element operators $exists and $type check fields, $regex matches patterns, and array operators $all, $size and $elemMatch query inside arrays. Projections choose returned fields, and sort, skip and limit shape the result.
26

How does change detection work in Angular, and what does OnPush do?

Save to ▾
Show answer
Change detection checks component bindings and updates the DOM when data changes. Traditionally Zone.js patched async APIs and triggered a check of the whole tree after events, timers and HTTP calls. With ChangeDetectionStrategy.OnPush, a component is checked only when an input reference changes, an event fires inside it, an async pipe emits or a signal it reads changes. OnPush with immutable data greatly reduces work.
27

Write an Nginx server block that serves Angular and proxies /api to Node.

Save to ▾
Show answer
One domain, no CORS needed. server { listen 80; server_name shop.example.com; root /usr/share/nginx/html; location /api/ { proxy_pass http://api:3000; proxy_set_header Host $host; proxy_set_header X-Forwarded-For $proxy_add_x_forwarded_for; } location / { try_files $uri $uri/ /index.html; } location ~* \.(js|css|woff2)$ { expires 1y; add_header Cache-Control "public, immutable"; } } Angular hashed file names make long caching safe.
28

What are typed reactive forms?

Save to ▾
Show answer
Since Angular 14, reactive forms are strongly typed. A FormControl<string> knows its value type, so form.value and getRawValue return typed objects and the compiler catches wrong field names. Controls are nullable by default because reset sets them to null; using nonNullable: true or NonNullableFormBuilder resets to the initial value instead. Typed forms make it safe to map form values directly to API request interfaces.
29

What are route guards and what kinds exist in modern Angular?

Save to ▾
Show answer
Guards decide whether navigation can proceed. canActivate checks before entering a route, canActivateChild covers child routes, canDeactivate runs before leaving, often to warn about unsaved changes, and canMatch decides whether a route definition even matches, useful for role-based lazy loading. Modern guards are plain functions using inject(), returning true, false, a UrlTree for redirect, or an Observable or Promise of these.
30

What are @defer blocks and how do they help performance?

Save to ▾
Show answer
@defer lets you lazy load part of a template and its dependencies only when a trigger occurs, such as on viewport, on interaction, on hover, on idle, on timer or a custom condition with when. Angular automatically splits that code into a separate chunk. You can show @placeholder, @loading and @error blocks. It is ideal for heavy below-the-fold widgets like charts, comments and maps.
31

A list API that uses Mongoose populate on three references has become slow. How would you improve it?

Save to ▾
Show answer
Check how many queries populate triggers and how much data each returns. Select only needed fields in populate, use lean(), and add indexes on the referenced fields. If the list always needs a customer name, store it with the extended reference pattern to avoid the join entirely. For complex filtering on related data, switch to one aggregation with $lookup and $project, and paginate.
32

Tell me about a complex form you built and the challenges you solved.

Save to ▾
Show answer
Situation: I built a loan application form with five steps and over sixty fields. Task: make it reliable and user friendly. Action: I used typed reactive forms split into step groups, cross-field validators for income rules, a FormArray for co-applicants, auto-saved drafts every thirty seconds and mapped server validation errors back to fields. Result: drop-offs reduced noticeably and QA found very few form bugs.
33

What is the difference between valueChanges and statusChanges, and what does updateOn do?

Save to ▾
Show answer
valueChanges is an Observable that emits the new value whenever a control or group changes, useful for dependent fields or type-ahead search. statusChanges emits when validation status changes between VALID, INVALID, PENDING and DISABLED. The updateOn option controls when value and validation update: change by default, blur to validate when the field loses focus, or submit to validate only on form submission.
34

How does Angular protect against cross-site scripting?

Save to ▾
Show answer
Angular treats all values as untrusted by default and sanitises them before inserting into the DOM: interpolation escapes HTML, and binding to innerHTML, styles or URLs is sanitised to strip dangerous content. Bypass methods in DomSanitizer, like bypassSecurityTrustHtml, should be used only for trusted content. Avoid direct DOM manipulation through ElementRef with user data, and add a Content Security Policy for defence in depth.
35

An order form lets users add any number of items with product, quantity and price. How do you build it?

Save to ▾
Show answer
Use a FormArray of FormGroups, each with product, quantity and price controls and validators like min(1). Provide addItem and removeItem methods that push or removeAt on the array, and render rows with @for over items.controls. Calculate the total from valueChanges or a computed signal. On submit, send getRawValue() typed as the order DTO, and disable the submit button while invalid or pending.
36

Write a custom pure pipe that shortens long text with an ellipsis.

Save to ▾
Show answer
Pipes are standalone by default. import { Pipe, PipeTransform } from '@angular/core'; @Pipe({ name: 'truncate' }) export class TruncatePipe implements PipeTransform { transform(value: string | null, limit = 50): string { if (!value) return ''; return value.length > limit ? value.slice(0, limit).trimEnd() + '...' : value; } } // add TruncatePipe to the component's imports, then: // {{ product.description | truncate:80 }} Because it is pure, it reruns only when the input string or limit changes.
37

Angular calls the Express API on a different port during development and gets CORS errors. What are your options?

Save to ▾
Show answer
In development, the cleanest fix is an Angular dev server proxy: a proxy.conf.json mapping /api to http://localhost:3000, so the browser sees same-origin requests. Alternatively enable the cors middleware in Express with the Angular origin allowed. In production, serve both under one domain through Nginx or configure CORS with an explicit allowlist, enabling credentials only when cookies are used.
38

An API sometimes returns null for a nested field and the Angular app crashes with cannot read properties of undefined. How do you fix it properly?

Save to ▾
Show answer
Model the API response accurately in TypeScript, marking the field as optional or nullable, and keep strictNullChecks on so the compiler forces you to handle it. Use optional chaining in code and templates, provide defaults with ??, and show a fallback in the UI with @if. Also agree with the backend team on the contract, and validate responses at the boundary if the data is untrusted.
39

Explain the four types of data binding in Angular.

Save to ▾
Show answer
Interpolation, {{ value }}, displays component data as text. Property binding, [src]='imageUrl', sets a DOM or component property. Event binding, (click)='save()', calls a method when an event fires. Two-way binding, [(ngModel)]='name' or [(value)] with a model input, combines property and event binding so the view and component stay in sync. Data flows one way by default, which keeps changes predictable.
40

What are async validators and when do you use them?

Save to ▾
Show answer
Async validators return an Observable or Promise of validation errors, used when validity needs a server check, such as whether a username or email is already taken. Angular runs them only after synchronous validators pass, and the control's status is PENDING meanwhile. Use updateOn: 'blur' or debounce inside the validator to avoid a request on every keystroke, and still enforce uniqueness on the backend.

Frequently asked questions

What is asked in MEAN Stack interviews for 2 years of experience?

At two years, questions shift to reasoning and trade-offs. Expect RxJS flattening operators, subscription leaks, signals versus subjects, OnPush change detection, lazy loading and typed forms with FormArray. On the backend, expect indexing, aggregation and JWT refresh flows. You should describe a performance or async bug you solved and show that you write unit tests with TestBed.

How many questions should I practise before a MEAN Stack interview?

Work through all 40 questions here, then the company-wise sets for the employers you are targeting. Quality matters more than count: be able to explain why each answer is right.

Which topics matter most for 2 years of experience?

Focus first on RxJS and signals, Change detection, MongoDB indexing, Unit testing.