Interview questions
Frontend Interview Questions & Answers
Questions first, then scroll down for answers. Click any question to jump to its answer.
JS Questions | TS Questions | React Questions | React Coding | Performance | System Design | Web Concepts | Security | Backend | DSA | Scenarios | Behavioral | Next.js | NestJS | All Answers
JS JavaScript (Core Depth)
- Explain the JavaScript event loop. Microtasks vs macrotasks?
- Explain closures with a real-world example.
- Explain hoisting in JavaScript.
- How does prototypal inheritance work?
- Difference between var, let, and const?
- Difference between == and ===?
- Explain shallow copy vs deep copy. Implement deep clone.
- How does `this` behave in arrow functions, class methods, and event handlers?
- Explain call, apply, and bind with use cases.
- Explain promises, async/await with real examples.
- Implement Promise.all from scratch. How is Promise.allSettled different?
- Implement debounce and throttle from scratch.
- Write polyfills (map, reduce, bind).
- Is JavaScript tightly coupled or loosely coupled?
- Difference between fetch and axios?
- Write code to find frequency of elements in an array.
- Difference between microtask and macrotask queue with a real example.
- Event Delegation & Bubbling.
TS TypeScript
- Why do we use TypeScript?
- How does "extends" work in TypeScript? Difference between type and interface?
React React (Core Concepts)
- What is React and why is it efficient?
- How does React work internally?
- Explain React Fiber.
- What is reconciliation? How does React diffing work?
- Why are keys important in lists?
- Explain React rendering lifecycle.
- Difference between state and props in React.
- Controlled vs uncontrolled components.
- What causes unnecessary re-renders? How do you avoid them?
- Explain useEffect deeply. Cleanup? Dependency array pitfalls?
- Difference between useMemo and useCallback. When would you use React.memo?
- What is state batching? What changed in React 18?
- How does React Context work? When can it hurt performance?
- Build a custom hook like useDebounce or useFetch.
- How does Redux work, from installation to usage?
- Redux Toolkit vs Redux? TanStack Query?
- What are stale closures in React?
- What causes memory leaks in React apps?
- Component Lifecycle.
- What are Error Boundaries? Explain implementation.
- How do you handle errors in React applications?
- What is state scheduling?
- How to send data from parent to child? What is prop drilling?
React React Coding Questions
- Build a debounced search input.
- Implement infinite scroll (Intersection Observer API).
- Create a custom useFetch hook with loading, error, and data.
- Prevent unnecessary re-renders using React.memo, useMemo, useCallback.
- Build form with controlled inputs + validation.
- Implement Dark/Light Mode using Context API.
- Role-Based Routing with JWT + React Router.
- Shopping Cart Logic (add/remove/update quantity + total).
- File Upload with Preview.
- Build a Modal from Scratch (reusable, ESC key, backdrop).
- Create a reusable dropdown with search and multi-select.
- Build a product listing page with search, filters, and cart.
- Design a reusable toast notification system.
Perf Performance & Optimization
- How do you optimize performance of a React application?
- What is lazy loading?
- What is code splitting?
- What is tree shaking?
- Explain repaint vs reflow vs compositing.
- How does browser rendering work internally?
- How do you optimize bundle size in React?
- How would you improve Web Vitals (LCP, CLS, INP)?
- Explain browser caching strategies.
- How do you debug frontend performance bottlenecks?
- What causes UI jank?
- How to optimize React rendering for large lists (10k+ rows)?
- What is WebSocket?
- What is Service Worker?
Design Frontend System Design
- Design an autocomplete search with debouncing and caching.
- Design an infinite scrolling feed.
- How would you design a scalable dashboard with 100+ pages?
- Design a reusable component library for a large team.
- Redux vs Context vs Zustand — how do you decide?
- SSR vs SSG vs ISR — when would you use each?
- How to architect a scalable frontend for 1M+ users daily?
- How to optimize an eCommerce product listing page?
- Design a Real-time Dashboard (with failure handling).
- Handle API caching on client.
Web Web Concepts & Browser
- Difference between CSR, SSR, SSG, ISR, and hydration?
- Explain hydration mismatch.
- What happens when a user types a URL in the browser?
- Difference between localStorage and sessionStorage?
- Explain optimistic UI updates.
- Explain race conditions in frontend applications.
- How do you cancel ongoing API requests in React?
- How do you handle API retries and failures?
- How do you handle API rate limits on the frontend?
- How do you monitor frontend applications in production?
- Explain accessibility best practices.
- REST APIs & HTTP Methods.
- Explain CORS in simple terms.
- Difference between synchronous and asynchronous JavaScript?
Sec Security & Authentication
- How do you prevent XSS, CSRF, and token leakage?
- How do you securely store tokens in frontend apps?
- Explain authentication vs authorization.
- Explain JWT authentication end-to-end with refresh flow.
- How do refresh tokens work internally?
- Frontend security vulnerabilities developers should know.
Node Backend (Node.js / Database)
- How do you design scalable REST APIs in Node.js?
- Explain authentication using JWT and refresh tokens (backend).
- How to handle caching and performance optimization in backend?
- SQL vs NoSQL — when to choose MongoDB over MySQL?
- Explain indexing and query optimization techniques.
- Design a scalable e-commerce or chat application architecture.
DSA Data Structures & Algorithms
- Find the second largest element in an array (O(n)).
- Maximum sum subarray (Kadane's algorithm).
- Sliding window maximum.
- Merge k sorted linked lists.
- Detect a cycle in a linked list.
- Longest palindromic substring.
- Design and implement an LRU Cache.
- Remove duplicate objects from an array based on a key.
Debug Scenario-Based / Debugging
- Duplicate API Calls Issue in SPA.
- Works in Staging, Fails in Production.
- Bundle is Slow After Deployment.
- React Re-renders — too many unnecessary re-renders.
- System Design + Failure Handling (Real-time Dashboard).
HR Behavioral / Managerial
- Tell me about a challenging production issue you resolved.
- How do you handle code reviews and mentor junior developers?
- How do you manage conflicting priorities?
- What's your approach when requirements change during sprint?
- How do you handle disagreements in technical decisions?
- How do you balance performance vs feature delivery?
- How do you prioritize technical debt vs new features?
- How do you explain technical decisions to non-technical stakeholders?
- What is the most challenging task you handled in your project?
- Explain a frontend project you built end-to-end.
- Why migrate from Angular to React? Challenges?
- How do you handle conflicts with designers or backend teams?
Next Next.js
- What is Next.js and how does it differ from plain React?
- Explain SSR, SSG, ISR, and CSR — when would you choose each?
- App Router vs Pages Router — key differences?
- What are React Server Components? How do they work in Next.js?
- Difference between Server Component and Client Component?
- How does data fetching work in the App Router?
- What is Incremental Static Regeneration (ISR)? How does revalidation work?
- How does caching work in Next.js 13+? (fetch cache, revalidateTag)
- What are Server Actions in Next.js?
- How does Next.js routing work? (dynamic routes, catch-all, parallel routes)
- How do you handle authentication in Next.js using Middleware?
- How does Next.js optimize images and fonts?
- What is Next.js Middleware and what can you use it for?
- How do you manage environment variables in Next.js?
- How do you optimize performance in a Next.js application?
Nest NestJS
- What is NestJS and how does it differ from Express?
- Explain the Module, Controller, and Provider pattern in NestJS.
- How does Dependency Injection work in NestJS?
- What are Guards, Pipes, Interceptors, and Middleware? What is their execution order?
- How do you implement JWT authentication in NestJS?
- How do you implement RBAC (Role-Based Access Control) in NestJS?
- What are DTOs and how does validation work with class-validator?
- How do decorators work in NestJS? Build a custom decorator.
- How do you integrate TypeORM or Prisma with NestJS?
- How do you implement microservices communication in NestJS?
- What is the difference between DEFAULT, REQUEST, and TRANSIENT provider scopes?
- How do you implement caching in NestJS?
- How do you test a NestJS application? (unit + e2e)
- How do you handle exceptions in NestJS? (Exception Filters)
- What is CQRS pattern in NestJS and when would you use it?
Interview Process References
| Company | Package | Rounds |
|---|---|---|
| EY (Sr Software Developer, 4+ yrs) | 28 LPA | R1: React/JS/DSA → R2: Node/System Design/DB → R3: Behavioral |
| Meesho | — | R1: OA (HackerEarth) → R2: JS Phone Screen → R3: Machine Coding → R4: LLD → R5: Hiring Manager |
Answers
Click any question above to jump here, or scroll through all answers below.
JS JavaScript — Answers
1. Event Loop, Microtasks vs Macrotasks
JS runs one thing at a time (single-threaded). The event loop checks: "Is the call stack empty? If yes, pick the next task from the queue."
Microtasks (Promises) always run BEFORE macrotasks (setTimeout).
console.log("1");
setTimeout(() => console.log("2"), 0); // macrotask
Promise.resolve().then(() => console.log("3")); // microtask
console.log("4");
// Output: 1, 4, 3, 2
// Why? Sync code first (1, 4) → microtask (3) → macrotask (2)
Back to questions
2. Closures
A function that remembers variables from where it was created, even after that outer function is done.
function counter() {
let count = 0;
return function() { return ++count; };
}
const inc = counter();
inc(); // 1
inc(); // 2 (it remembers count!)
Used for: keeping data private, factory functions, event handlers.
Back to questions3. Hoisting
JS moves declarations to the top before running code.
- var → moved up, starts as
undefined - let/const → moved up but CAN'T use before their line (Temporal Dead Zone → error)
- function declarations → fully moved up, can call before their line
- Arrow functions → NOT hoisted
4. Prototypal Inheritance
Every object has a parent object (prototype). If a property isn't found on the object, JS looks at its parent, then grandparent, and so on.
const animal = { speak() { return "hello"; } };
const dog = Object.create(animal);
dog.speak(); // works! Found it on parent (animal)
Back to questions
5. var vs let vs const
| Feature | var | let | const |
|---|---|---|---|
| Scope | Function | Block { } | Block { } |
| Re-declare | Yes | No | No |
| Re-assign | Yes | Yes | No |
| Hoisting | undefined | TDZ (error) | TDZ (error) |
Note: const objects can still have properties changed: const obj = {}; obj.name = "John"; // works!
6. == vs ===
- == (loose): converts types then compares.
"5" == 5 → true - === (strict): does NOT convert types.
"5" === 5 → false
Always use === to avoid surprises.
Back to questions7. Shallow Copy vs Deep Copy
- Shallow copy: copies first level only. Nested objects still point to original.
- Deep copy: copies everything including nested objects.
// Shallow copy
const copy = { ...original };
// Deep copy (modern)
const copy = structuredClone(original);
// Deep copy (older)
const copy = JSON.parse(JSON.stringify(original));
// Manual deep clone
function deepClone(obj) {
if (obj === null || typeof obj !== 'object') return obj;
const clone = Array.isArray(obj) ? [] : {};
for (let key in obj) {
if (obj.hasOwnProperty(key)) clone[key] = deepClone(obj[key]);
}
return clone;
}
Back to questions
8. `this` Behavior
| Context | this points to |
|---|---|
| Object method | The object itself |
| Regular function | window (browser) / undefined (strict) |
| Arrow function | Takes `this` from parent scope |
| Event handler | The element clicked |
| Class method | The instance |
Lost `this`? Use .bind(this) or arrow function to fix.
9. call, apply, bind
All three let you set what `this` should be.
function greet(msg) { return `${msg}, ${this.name}`; }
// call → runs NOW, args one by one
greet.call({ name: "John" }, "Hi"); // "Hi, John"
// apply → runs NOW, args as array
greet.apply({ name: "John" }, ["Hi"]); // "Hi, John"
// bind → returns NEW function for later
const bound = greet.bind({ name: "John" });
bound("Hi"); // "Hi, John"
Back to questions
10. Promises & async/await
Promise = "I'll give you the result later" (pending → success or fail).
async/await = cleaner way to write promises.
// Promise way
fetch(url).then(res => res.json()).then(data => console.log(data)).catch(err => console.error(err));
// async/await way (same thing, cleaner)
async function getData() {
try {
const res = await fetch(url);
const data = await res.json();
console.log(data);
} catch (err) { console.error(err); }
}
Back to questions
11. Implement Promise.all
Runs multiple promises together, returns all results. Fails if ANY one fails.
function promiseAll(promises) {
return new Promise((resolve, reject) => {
const results = [];
let done = 0;
if (promises.length === 0) return resolve([]);
promises.forEach((p, i) => {
Promise.resolve(p)
.then(val => {
results[i] = val;
if (++done === promises.length) resolve(results);
})
.catch(reject);
});
});
}
Promise.allSettled: waits for ALL, never fails early. Use when you want all results even if some fail.
Back to questions12. Debounce & Throttle
Debounce: wait until user STOPS, then run. Throttle: run at most once every X ms.
// Debounce (e.g., search after typing stops)
function debounce(fn, delay) {
let timer;
return (...args) => {
clearTimeout(timer);
timer = setTimeout(() => fn(...args), delay);
};
}
// Throttle (e.g., scroll handler fires max once per 200ms)
function throttle(fn, limit) {
let lastCall = 0;
return (...args) => {
if (Date.now() - lastCall >= limit) {
lastCall = Date.now();
fn(...args);
}
};
}
Back to questions
13. Polyfills (map, reduce, bind)
// map: transform each item, return new array
Array.prototype.myMap = function(cb) {
const result = [];
for (let i = 0; i < this.length; i++) result.push(cb(this[i], i, this));
return result;
};
// reduce: combine all items into single value
Array.prototype.myReduce = function(cb, init) {
let acc = init !== undefined ? init : this[0];
for (let i = init !== undefined ? 0 : 1; i < this.length; i++) acc = cb(acc, this[i], i, this);
return acc;
};
// bind: create new function with fixed `this`
Function.prototype.myBind = function(ctx, ...args) {
const fn = this;
return (...newArgs) => fn.apply(ctx, [...args, ...newArgs]);
};
Back to questions
14. JS Coupling
Loosely coupled — parts of code can work independently. We achieve this using modules (import/export), events, callbacks. Tightly coupled = changing one part breaks another.
Back to questions15. fetch vs axios
| Feature | fetch | axios |
|---|---|---|
| Built-in? | Yes (browser native) | No (install separately) |
| JSON parsing | Need .json() | Auto-parses |
| Error on 404/500 | Does NOT throw | DOES throw |
| Interceptors | No | Yes |
| Cancel request | AbortController | Built-in cancel |
16. Frequency of Elements
function frequency(arr) {
return arr.reduce((acc, val) => {
acc[val] = (acc[val] || 0) + 1;
return acc;
}, {});
}
frequency([1,2,2,3,3,3]); // { 1:1, 2:2, 3:3 }
Back to questions
17. Microtask vs Macrotask
- Microtask (high priority): Promise.then — runs right after current code finishes.
- Macrotask (lower priority): setTimeout — runs in next round.
- ALL microtasks finish BEFORE any macrotask runs.
18. Event Delegation & Bubbling
Bubbling: click on child → event goes UP to parent → grandparent → ...
Event Delegation: add ONE click on parent, check which child was clicked.
ul.addEventListener("click", (e) => {
if (e.target.tagName === "LI") console.log(e.target.textContent);
});
Why? Fewer listeners, works for dynamically added items.
Back to questionsTS TypeScript — Answers
1. Why TypeScript
- Catches errors BEFORE running the code (compile time).
- Better autocomplete in VS Code.
- Code is self-documenting (you see types).
- Easier teamwork on large projects.
2. extends & type vs interface
// extends: one interface builds on top of another
interface Animal { name: string; }
interface Dog extends Animal { breed: string; }
// Dog has both name + breed
// interface: for object shapes, auto-merges
interface User { name: string; }
interface User { age: number; } // merged!
// type: more flexible — unions, tuples, etc.
type ID = string | number; // can't do with interface
Simple rule: Use interface for objects, type for everything else.
Back to questionsReact React Core — Answers
1. What is React
A JS library to build UI using reusable components. Fast because of Virtual DOM — only updates what actually changed on screen.
Back to questions2. How React Works Internally
You write JSX
↓
React converts to JS objects (Virtual DOM)
↓
When state changes → new Virtual DOM created
↓
React COMPARES old vs new (diffing)
↓
Only the CHANGED parts get updated on real screen
Back to questions
3. React Fiber
React's internal engine (since React 16). Breaks big rendering into small pieces so browser doesn't freeze. Can pause, prioritize, and resume work.
Example: user typing (high priority) won't be blocked by data loading (low priority).
Back to questions4. Reconciliation & Diffing
- React compares old and new Virtual DOM trees.
- Different element type? → Rebuild everything below.
- Same type? → Update changed attributes only.
- Lists? → Uses "key" to track items.
5. Why Keys Matter
Keys tell React which item is which in a list. Without keys → mix-ups and unnecessary re-renders. Use unique IDs, NOT array index (breaks when list order changes).
Back to questions6. React Lifecycle
Mount (born) → component appears → useEffect(() => {}, []) runs
Update (changed) → state/props change → re-render → useEffect runs again
Unmount (dies) → component removed → useEffect cleanup runs
Back to questions
7. State vs Props
| Feature | Props | State |
|---|---|---|
| Source | From parent | Inside component |
| Mutable? | Read-only | Can change (useState) |
| Direction | Flows down | Local only |
8. Controlled vs Uncontrolled
// Controlled: React controls the value
<input value={name} onChange={e => setName(e.target.value)} />
// Uncontrolled: DOM controls the value, read with ref
<input ref={myRef} /> → myRef.current.value
Controlled = more control (validation). Uncontrolled = simpler.
Back to questions9. Unnecessary Re-renders
Causes: parent re-renders → child re-renders too, new object/function refs created every render.
Fix: React.memo (skip re-render if props same), useMemo (cache values), useCallback (cache functions).
Back to questions10. useEffect
useEffect(() => {
// runs AFTER render
return () => { /* cleanup */ };
}, [deps]);
// [] → run once (mount)
// [x] → run when x changes
// nothing → every render
Mistakes: forgetting deps (stale data), object deps (new ref → infinite loop).
Back to questions11. useMemo vs useCallback vs React.memo
useMemo → caches a VALUE: const total = useMemo(() => calc(items), [items])
useCallback → caches a FUNCTION: const handleClick = useCallback(() => {...}, [deps])
React.memo → wraps a COMPONENT to skip re-render if props unchanged
Back to questions
12. State Batching
React groups multiple setState calls into ONE re-render (for performance).
- React 17: batched only inside click handlers.
- React 18: batches EVERYWHERE — setTimeout, promises, etc.
13. Context API
Share data across components without prop drilling: Create → Provide → Consume (useContext).
Problem: ALL consumers re-render when value changes. Fix: split into multiple contexts or use Zustand/Redux for frequent updates.
Back to questions14. Custom Hooks
// useDebounce — delays value updates
function useDebounce(value, delay) {
const [debounced, setDebounced] = useState(value);
useEffect(() => {
const timer = setTimeout(() => setDebounced(value), delay);
return () => clearTimeout(timer);
}, [value, delay]);
return debounced;
}
// useFetch — fetches data from URL
function useFetch(url) {
const [data, setData] = useState(null);
const [loading, setLoading] = useState(true);
const [error, setError] = useState(null);
useEffect(() => {
fetch(url).then(r => r.json()).then(setData).catch(setError).finally(() => setLoading(false));
}, [url]);
return { data, loading, error };
}
Back to questions
15. Redux
One big STORE holds all app state
↓
Component DISPATCHES an ACTION → dispatch({ type: "ADD_ITEM", payload: item })
↓
REDUCER returns NEW state → (state, action) => newState
↓
Component RE-RENDERS with new data
Back to questions
16. RTK vs Redux vs TanStack Query
- RTK: simpler, less code, uses createSlice (auto-creates actions + reducer).
- Old Redux: more boilerplate (action types, switch cases).
- TanStack Query: for server state (fetching/caching API data) — different from client state management.
17. Stale Closures
A function remembers OLD state value instead of the current one. Common in useEffect with empty deps — setTimeout captures initial state.
Fix: add correct dependencies, or use setState(prev => prev + 1) (functional update).
18. Memory Leaks
Caused by: timers not cleared, event listeners not removed, fetch requests not cancelled after component unmounts.
Fix: always return cleanup in useEffect.
useEffect(() => {
const timer = setInterval(fetchData, 5000);
return () => clearInterval(timer); // cleanup!
}, []);
Back to questions
19. Component Lifecycle
Mount → Render → useEffect → Update → Re-render → useEffect cleanup + re-run → Unmount → Final cleanup.
Back to questions20. Error Boundaries
Catches errors in children — like try-catch for UI. Shows fallback UI instead of crashing the whole app. Must be a class component with getDerivedStateFromError.
Does NOT catch: event handler errors, async errors (use try-catch for those).
Back to questions21. Error Handling
UI errors → Error Boundaries. Async/event errors → try-catch. Log errors to services like Sentry or LogRocket. Show friendly error states to users.
Back to questions22. State Scheduling
React doesn't apply state updates instantly — it schedules them. startTransition marks an update as "not urgent, do it when free" — keeps typing and interactions smooth while heavy updates happen in the background.
23. Props & Prop Drilling
Pass data from parent to child using props. Prop drilling = passing props through many middle components that don't need them.
Fix: Context API, Redux, Zustand, or component composition.
Back to questionsReact React Coding — Answers
1. Debounced Search
const [query, setQuery] = useState("");
const debounced = useDebounce(query, 500);
useEffect(() => { if (debounced) searchAPI(debounced); }, [debounced]);
return <input value={query} onChange={e => setQuery(e.target.value)} />;
Back to questions
2. Infinite Scroll
const loaderRef = useRef();
useEffect(() => {
const observer = new IntersectionObserver(entries => {
if (entries[0].isIntersecting) loadMore();
});
observer.observe(loaderRef.current);
return () => observer.disconnect();
}, []);
// At bottom of list: <div ref={loaderRef}>Loading...</div>
Back to questions
3. useFetch Hook
See React Core Q14 above for full code. Returns { data, loading, error }.
4. Prevent Re-renders
const Child = React.memo(({ onClick }) => <button onClick={onClick}>Click</button>);
function Parent() {
const handleClick = useCallback(() => doSomething(), []);
const data = useMemo(() => expensiveCalc(input), [input]);
return <Child onClick={handleClick} />;
}
Back to questions
5. Form Validation
const [email, setEmail] = useState("");
const [error, setError] = useState("");
const submit = () => {
if (!/\S+@\S+\.\S+/.test(email)) setError("Invalid email");
else { setError(""); sendData(email); }
};
Back to questions
6. Dark/Light Mode
const ThemeCtx = createContext();
function ThemeProvider({ children }) {
const [theme, setTheme] = useState("light");
const toggle = () => setTheme(t => t === "light" ? "dark" : "light");
return <ThemeCtx.Provider value={{ theme, toggle }}>{children}</ThemeCtx.Provider>;
}
// Use: const { theme, toggle } = useContext(ThemeCtx);
// Apply: <div className={theme}>
Back to questions
7. Protected Route
function ProtectedRoute({ children, role }) {
const user = getUser(); // decode JWT from cookie/storage
if (!user) return <Navigate to="/login" />;
if (user.role !== role) return <Navigate to="/403" />;
return children;
}
Back to questions
8. Cart Logic
Add: setCart([...cart, { ...product, qty: 1 }])
Remove: setCart(cart.filter(i => i.id !== id))
Update qty: setCart(cart.map(i => i.id === id ? {...i, qty} : i))
Total: cart.reduce((sum, i) => sum + i.price * i.qty, 0)
Back to questions
9. File Upload Preview
const [preview, setPreview] = useState(null);
const handleFile = (e) => setPreview(URL.createObjectURL(e.target.files[0]));
// <input type="file" onChange={handleFile} />
// {preview && <img src={preview} alt="preview" />}
Back to questions
10. Modal from Scratch
function Modal({ isOpen, onClose, children }) {
useEffect(() => {
const esc = (e) => { if (e.key === "Escape") onClose(); };
if (isOpen) document.addEventListener("keydown", esc);
return () => document.removeEventListener("keydown", esc);
}, [isOpen]);
if (!isOpen) return null;
return createPortal(
<div className="backdrop" onClick={onClose}>
<div className="modal" onClick={e => e.stopPropagation()}>{children}</div>
</div>, document.getElementById("modal-root")
);
}
Back to questions
11. Multi-Select Dropdown
Filter options by search text, toggle selection with checkboxes, show selected count in the trigger button.
const [selected, setSelected] = useState([]);
const [search, setSearch] = useState("");
const filtered = options.filter(o => o.label.toLowerCase().includes(search.toLowerCase()));
const toggle = (val) => setSelected(s => s.includes(val) ? s.filter(x => x !== val) : [...s, val]);
Back to questions
12. Product Listing Page
- State: useReducer for filters + cart, URL params (useSearchParams) to reflect active filters.
- Cart persistence: useEffect to sync cart to localStorage on change.
- Memoization: React.memo on product cards, useMemo for filtered product list.
- Skeleton loaders: show placeholder cards while fetching, replace with real data on load.
13. Toast Notification System
- State: array of toasts in Context, each with id, message, type, duration.
- Auto-dismiss: useEffect per toast with setTimeout → remove by id.
- Accessibility:
aria-live="polite"on container so screen readers announce new toasts. - Framework-agnostic: expose a vanilla JS API (
toast.show()) that dispatches a custom DOM event.
Perf Performance — Answers
1. Optimize React App
- Code splitting & lazy loading (React.lazy + Suspense)
- React.memo, useMemo, useCallback to prevent re-renders
- Virtualize long lists (react-window / react-virtual)
- Debounce/throttle expensive operations
- Optimize images (WebP, lazy load, proper sizing)
- Reduce bundle size, enable gzip/brotli compression
2. Lazy Loading
Load things only when needed — saves bandwidth and speeds up initial load.
- Images:
<img loading="lazy" /> - Components:
const Page = React.lazy(() => import('./Page'))
3. Code Splitting
Break app into smaller JS files. Load each page's code only when user visits it. Uses dynamic import() — bundler creates separate chunks automatically.
4. Tree Shaking
Bundler removes unused code automatically. Requires ES modules (import/export), not CommonJS (require). Example: importing only { format } from date-fns instead of the whole library.
5. Repaint vs Reflow vs Compositing
| Type | Triggered by | Cost |
|---|---|---|
| Reflow (Layout) | Size/position changes | Most expensive |
| Repaint | Color/background changes | Medium |
| Compositing | transform/opacity (GPU) | Cheapest |
Use transform and opacity for animations — they skip layout and paint entirely.
Back to questions6. Browser Rendering
HTML → DOM Tree
CSS → CSSOM Tree
↓
Render Tree (visible nodes only)
↓
Layout (calculate positions/sizes)
↓
Paint (fill pixels)
↓
Composite (GPU layers → screen)
Back to questions
7. Optimize Bundle Size
- Analyze with webpack-bundle-analyzer or vite's rollup-plugin-visualizer
- Replace heavy libs: moment.js → dayjs, lodash → individual imports
- Enable gzip/brotli in server config
- Code-split routes, lazy-load heavy components
- Use CDN for large static assets
8. Web Vitals (LCP, CLS, INP)
- LCP (Largest Contentful Paint — loading speed): optimize hero images, preload fonts, use SSR, CDN.
- CLS (Cumulative Layout Shift — visual stability): set explicit sizes on images/videos, don't inject content above existing content.
- INP (Interaction to Next Paint — responsiveness): don't block main thread, debounce inputs, use Web Workers for heavy tasks.
9. Browser Caching
- Cache-Control headers:
max-age=31536000for hashed static assets (CSS/JS),no-cachefor HTML. - ETags: server sends a fingerprint — browser sends it back, server replies 304 Not Modified if unchanged.
- Service Worker: cache assets offline, serve from cache-first or network-first strategy.
10. Debug Performance
- Chrome DevTools Performance tab: record interactions, see long tasks and bottlenecks.
- Lighthouse: automated audit for Web Vitals, accessibility, best practices.
- React Profiler: find which components re-render and how long they take.
- web-vitals library: measure LCP/CLS/INP in real user sessions.
11. UI Jank
Screen freezes when the main thread is busy for more than 16ms (1 frame at 60fps).
Fix: move heavy work to Web Workers, use GPU animations (transform/opacity), debounce scroll/resize handlers, virtualize long lists.
Back to questions12. Large Lists (10k+ rows)
Use virtualization — only render the rows currently visible in the viewport, not all 10,000.
Libraries: react-window (lightweight) or @tanstack/react-virtual (more flexible).
Back to questions13. WebSocket
A persistent two-way connection between browser and server. Unlike HTTP (request-response), server can push data at any time.
Use cases: chat apps, live dashboards, stock tickers, multiplayer games.
const ws = new WebSocket("wss://example.com/ws");
ws.onmessage = (e) => console.log(e.data);
ws.send("hello server");
Back to questions
14. Service Worker
A background script that runs separately from the page. Acts as a proxy between browser and network.
- Offline caching: intercept fetch requests, serve from cache when offline.
- Push notifications: receive messages even when app is closed.
- Background sync: queue actions when offline, replay when back online.
Design System Design — Answers
1. Autocomplete Search
Debounce input (300ms) → cancel previous request (AbortController) → call API → cache results in a Map → show dropdown → support keyboard navigation (ArrowUp/Down/Enter).
Back to questions2. Infinite Feed
IntersectionObserver at bottom sentinel → load next page (cursor-based pagination) → append items → virtualize with react-window for performance → show skeleton loaders while fetching.
Back to questions3. Scalable Dashboard (100+ pages)
- Lazy-load each page with React.lazy + Suspense
- Feature-based folder structure (not file-type-based)
- Shared layout with nested routing (React Router v6)
- Micro-frontends for large teams (Module Federation)
- Prefetch next likely pages on hover
4. Reusable Component Library
- Design tokens: colors, spacing, typography as CSS variables
- Storybook: live docs + visual testing for every component
- npm package: publish with proper tree-shaking exports
- Accessibility: ARIA roles, keyboard navigation baked in
- TypeScript: typed props for autocomplete and safety
5. Redux vs Context vs Zustand
| Context | Redux (RTK) | Zustand | |
|---|---|---|---|
| Best for | Theme, auth (low freq) | Complex apps, devtools | Medium apps, simple API |
| Boilerplate | None | Moderate | Minimal |
| Frequent updates | Bad (all re-render) | Good | Good |
6. SSR vs SSG vs ISR
- SSR: server renders on every request. Good for dynamic/personalized content and SEO.
- SSG: pages built once at deploy time. Fastest possible — great for blogs, docs.
- ISR: SSG + pages auto-regenerate in background after a set time. Best of both worlds.
7. Scalable Frontend for 1M+ Users
CDN for static assets → code split + lazy load → service workers for offline → performance monitoring → edge caching (Cloudflare) → micro-frontends for team scalability.
Back to questions8. eCommerce Product Listing
SSR for first page (SEO) → lazy-load images (next/image) → virtualized grid for large catalogs → skeleton loaders → debounced search → TanStack Query for client-side caching.
Back to questions9. Real-time Dashboard
WebSocket for live data → auto-reconnect with exponential backoff → buffer/queue updates to avoid UI flooding → Web Workers for heavy data processing → show stale cached data while reconnecting.
Back to questions10. Client-side API Caching
- TanStack Query / SWR: auto-caching, stale-while-revalidate, background refetch, deduplication of requests.
- Manual:
const cache = new Map()with TTL check before fetching.
Web Web Concepts — Answers
1. CSR vs SSR vs SSG vs ISR
CSR → Browser renders everything (slow first load, fast navigation) SSR → Server sends ready HTML (fast first load, good SEO) SSG → HTML built at deploy time (fastest, good for static content) ISR → SSG + pages auto-refresh in background after TTL Hydration → Making server HTML interactive by attaching JS event listenersBack to questions
2. Hydration Mismatch
Server HTML ≠ client HTML. React throws a warning and re-renders from scratch.
Causes: using window, Date.now(), localStorage, or random values during render.
Fix: move client-only code into useEffect.
3. What Happens When You Type a URL
1. DNS lookup → resolve domain to IP address 2. TCP + TLS handshake → establish secure connection 3. HTTP request sent → GET /path HTTP/1.1 4. Server responds → HTML, status 200 5. Browser parses HTML → builds DOM 6. Fetches CSS → builds CSSOM → Render Tree 7. Fetches JS → executes scripts 8. Layout → Paint → Composite → ScreenBack to questions
4. localStorage vs sessionStorage
| localStorage | sessionStorage | |
|---|---|---|
| Lifetime | Forever (manual clear) | Until tab closes |
| Scope | All tabs (same origin) | Per tab only |
| Size | ~5MB | ~5MB |
5. Optimistic UI
Update the UI instantly before the server responds. If server fails, roll back. Makes the app feel faster.
Example: hitting Like instantly turns the icon red, then if the API call fails you flip it back and show an error.
Back to questions6. Race Conditions
Two API calls finish in the wrong order — the older response overwrites the newer one.
Fix: use AbortController to cancel the previous request when a new one starts.
Back to questions7. Cancel API Requests
useEffect(() => {
const controller = new AbortController();
fetch(url, { signal: controller.signal })
.then(r => r.json()).then(setData)
.catch(e => { if (e.name !== "AbortError") setError(e); });
return () => controller.abort(); // cancel on cleanup
}, [url]);
Back to questions
8. API Retries & Failures
Retry with exponential backoff (1s, 2s, 4s...), max 3–5 attempts. Only retry on network errors or 5xx, not 4xx. Show spinner during retry, show error state if all fail.
Back to questions9. API Rate Limits (HTTP 429)
When server returns 429 Too Many Requests: queue further requests, respect the Retry-After header, increase client-side caching to reduce call frequency, debounce user-triggered actions.
10. Monitor Frontend
- Sentry: capture JS errors with stack traces and user context.
- web-vitals: measure LCP/CLS/INP from real users.
- Google Analytics / Datadog RUM: user flows and performance.
11. Accessibility
- Use semantic HTML (
<button>not<div onClick>,<nav>,<main>) - Alt text on images, labels on form inputs
- Full keyboard navigation (Tab, Enter, Escape, Arrow keys)
- Color contrast ratio ≥ 4.5:1 for text
- ARIA roles/labels where HTML semantics are insufficient
12. REST & HTTP Methods
| Method | Action | Idempotent? |
|---|---|---|
| GET | Read | Yes |
| POST | Create | No |
| PUT | Replace | Yes |
| PATCH | Partial update | No |
| DELETE | Remove | Yes |
13. CORS
Browser blocks requests to a different origin (domain/port/protocol) for security. Server must explicitly allow it.
// Server response header: Access-Control-Allow-Origin: https://yourapp.com Access-Control-Allow-Methods: GET, POST, PUTBack to questions
14. Sync vs Async
Synchronous: one task blocks until it finishes — next line can't run. Asynchronous: start a task and move on — handle result later via callback/promise/await.
Back to questionsSec Security — Answers
1. XSS & CSRF Prevention
- XSS: never use innerHTML with user input. React escapes JSX by default. Sanitize with DOMPurify if you must render HTML. Add Content-Security-Policy headers.
- CSRF: use CSRF tokens in forms, set cookies with
SameSite=StrictorSameSite=Lax.
2. Store Tokens Safely
Best: httpOnly cookies (JS cannot access them — safe from XSS). Set Secure + SameSite flags.
NEVER: localStorage or sessionStorage — any XSS attack can steal tokens stored there.
Back to questions3. Authentication vs Authorization
Authentication: proving WHO you are — login with email/password, OAuth, biometrics.
Authorization: checking WHAT you're allowed to do — role-based access, permissions.
Back to questions4. JWT Flow with Refresh Tokens
Login → server returns:
- Access token (short-lived: 15min) — stored in memory
- Refresh token (long-lived: 7 days) — stored in httpOnly cookie
↓
Every API call → send access token in Authorization header
↓
Access token expired → automatically send refresh token → get new access token
↓
Refresh token expired → redirect to login
↓
Logout → server invalidates refresh token
Back to questions
5. Refresh Tokens Internally
Stored in httpOnly cookie (not JS-accessible). When access token expires, browser automatically sends cookie to the refresh endpoint. Server validates it, invalidates the old refresh token (rotation), and issues new tokens. This prevents replay attacks.
Back to questions6. Frontend Security Vulnerabilities
| Attack | What it does | Fix |
|---|---|---|
| XSS | Inject malicious scripts | Sanitize input, CSP headers |
| CSRF | Trick user into unwanted actions | CSRF tokens, SameSite cookies |
| Clickjacking | Hidden iframe tricks clicks | X-Frame-Options: DENY |
| Outdated deps | Known vulnerabilities in packages | npm audit, Snyk, Dependabot |
Node Backend — Answers
1. Scalable REST API
Structure: routes → controllers → services → DB (separation of concerns). Add middleware for auth + validation. Use pagination for list endpoints. Add rate limiting (express-rate-limit). Log with Morgan/Winston.
Back to questions2. JWT Backend
Login → sign access + refresh tokens → middleware verifies access token on every protected route → POST /refresh endpoint validates refresh token and issues new pair → POST /logout invalidates refresh token in DB.
3. Backend Caching
Redis for frequently read data (user sessions, product listings). Set a TTL (time-to-live). On write operations, invalidate or update the relevant cache key. Use cache-aside pattern: check cache first, miss → DB → populate cache.
Back to questions4. SQL vs NoSQL
| SQL (MySQL / PostgreSQL) | NoSQL (MongoDB) | |
|---|---|---|
| Structure | Fixed tables + schema | Flexible documents |
| Relations | JOINs, foreign keys | Embedded docs or refs |
| Best for | Banking, e-commerce | Social media, real-time |
| Scaling | Vertical | Horizontal (sharding) |
5. Indexing
Create indexes on columns you frequently filter/search/join → speeds up reads dramatically. Composite index for multi-column queries.
Don't over-index: each index slows down writes (INSERT/UPDATE/DELETE) and takes storage.
Back to questions6. Scalable Architecture
- E-commerce: microservices (users, products, orders), message queue (RabbitMQ/Kafka) for order processing, Redis cache, CDN for images.
- Chat app: WebSocket server (Socket.io), MongoDB for message storage, Redis pub/sub for multi-server broadcast.
DSA DSA — Answers
1. Second Largest — O(n)
function secondLargest(arr) {
let first = -Infinity, second = -Infinity;
for (const n of arr) {
if (n > first) { second = first; first = n; }
else if (n > second && n !== first) second = n;
}
return second;
}
Back to questions
2. Kadane's Algorithm (Max Subarray)
function maxSum(arr) {
let max = arr[0], current = arr[0];
for (let i = 1; i < arr.length; i++) {
current = Math.max(arr[i], current + arr[i]); // extend or restart
max = Math.max(max, current);
}
return max;
}
Back to questions
3. Sliding Window Maximum
Use a deque (double-ended queue) of indices. Keep it in descending order of values. Remove indices that are out of the window. Front of deque is always the max for current window.
function maxSlidingWindow(nums, k) {
const dq = [], result = [];
for (let i = 0; i < nums.length; i++) {
while (dq.length && dq[0] < i - k + 1) dq.shift(); // out of window
while (dq.length && nums[dq[dq.length-1]] < nums[i]) dq.pop(); // smaller
dq.push(i);
if (i >= k - 1) result.push(nums[dq[0]]);
}
return result;
}
Back to questions
4. Merge K Sorted Lists
Use a min-heap. Push the head node of each list into the heap. Each step: extract the minimum, add to result, push that node's next into the heap. Time: O(N log k).
Simple approach (JS): collect all values → sort → rebuild linked list. Time: O(N log N).
Back to questions5. Detect Cycle — Floyd's Algorithm
function hasCycle(head) {
let slow = head, fast = head;
while (fast && fast.next) {
slow = slow.next; // 1 step
fast = fast.next.next; // 2 steps
if (slow === fast) return true;
}
return false;
}
Back to questions
6. Longest Palindromic Substring
For each character, expand outward while left and right characters match. Check both odd-length (center = one char) and even-length (center = two chars) palindromes.
function longestPalindrome(s) {
let res = "";
for (let i = 0; i < s.length; i++) {
for (const [l, r] of [[i, i], [i, i+1]]) {
let lo = l, hi = r;
while (lo >= 0 && hi < s.length && s[lo] === s[hi]) { lo--; hi++; }
if (hi - lo - 1 > res.length) res = s.slice(lo+1, hi);
}
}
return res;
}
Back to questions
7. LRU Cache
Use a Map — it preserves insertion order. On get: delete + re-insert to move to end (most recent). On put: if full, delete the first key (least recently used).
class LRUCache {
constructor(cap) { this.cap = cap; this.cache = new Map(); }
get(k) {
if (!this.cache.has(k)) return -1;
const v = this.cache.get(k);
this.cache.delete(k);
this.cache.set(k, v); // move to end (most recent)
return v;
}
put(k, v) {
this.cache.delete(k);
if (this.cache.size >= this.cap)
this.cache.delete(this.cache.keys().next().value); // remove LRU
this.cache.set(k, v);
}
}
Back to questions
8. Remove Duplicates by Key
function unique(arr, key) {
const seen = new Set();
return arr.filter(item =>
seen.has(item[key]) ? false : (seen.add(item[key]), true)
);
}
// unique([{id:1,name:"A"},{id:1,name:"B"},{id:2,name:"C"}], "id")
// → [{id:1,name:"A"}, {id:2,name:"C"}]
Back to questions
Debug Scenario-Based — Answers
1. Duplicate API Calls
- Check useEffect dependency array — missing or wrong deps cause multiple runs.
- React StrictMode double-invokes effects in dev — expected, not a bug.
- Add debouncing to user-triggered calls.
- Use AbortController to cancel duplicate in-flight requests.
- Add an in-progress flag or use TanStack Query (deduplicates by default).
2. Works in Staging, Fails in Prod
- Bundle size: prod has minification — check source maps, unexpected code paths.
- Memory leaks: use Chrome DevTools Memory tab under real traffic patterns.
- CDN caching stale JS: ensure filenames are cache-busted (content hash).
- Hydration mismatch: check for window/Date usage in render paths.
- Environment variables: verify prod env vars match staging.
3. Bundle Slow After Deployment
- Run Lighthouse before/after to isolate the change.
- Use webpack-bundle-analyzer — find what's new and large.
- Check for missing code splitting on new routes.
- Verify gzip/brotli is still enabled in server config.
- Check if a new dependency pulled in a heavy transitive dep.
4. Too Many Re-renders
- Open React Profiler → record interaction → see which components render and how long.
- Wrap expensive components with React.memo.
- Memoize callback props with useCallback, computed values with useMemo.
- Move state down — don't lift state higher than necessary.
- Split Context — one context causing mass re-renders → split into separate ones.
5. Real-time Dashboard Failures
| Problem | Solution |
|---|---|
| WebSocket disconnects | Auto-reconnect with exponential backoff, show "reconnecting" state |
| API rate limits hit | Queue requests, increase cache TTL, batch updates |
| Browser tab crashes | Persist last known state to localStorage, restore on reload |
| Traffic spikes 10× | CDN + load balancer, serve stale cached data, throttle updates to clients |
HR Behavioral — Answers
Always use STAR format: Situation → Task → Action → Result
1. Challenging Production Bug
Structure: What broke and how it impacted users → how you found the root cause (tools used) → exactly what you fixed → what you learned or put in place to prevent recurrence.
Back to questions2. Code Reviews & Mentoring
Reviews: focus on logic correctness and readability, give actionable suggestions (not criticism), ask questions rather than stating mistakes. Mentoring: pair programming, start with smaller tasks and increase complexity, explain the why not just the what.
Back to questions3. Conflicting Priorities
List tasks by business impact and urgency → communicate transparently with stakeholders about trade-offs → break large work into smaller deliverables so something ships → escalate if timelines conflict at an organizational level.
Back to questions4. Requirement Changes During Sprint
Assess impact on timeline and scope → discuss with PM immediately → small change: accommodate. Large change: negotiate next sprint. Document the change and update estimates. Avoid gold-plating — build only what's agreed.
Back to questions5. Technical Disagreements
Listen fully to all perspectives → argue with data and concrete examples, not opinions → build a small prototype if the trade-off is unclear → once a team decision is made, commit to it fully even if it wasn't your preference.
Back to questions6. Performance vs Feature Delivery
Performance IS a feature — slow apps lose users. Set measurable budgets (LCP < 2.5s, bundle < 200KB). Prioritize performance fixes that directly impact user retention or conversion. Automate perf checks in CI so they don't slip silently.
Back to questions7. Tech Debt vs Features
Dedicate ~20% of each sprint to tech debt. Prioritize debt that blocks feature work or causes recurring bugs. Frame it to stakeholders as an investment: "fixing this now saves 3 days per sprint." Don't touch debt that isn't causing pain.
Back to questions8. Explain to Non-Tech Stakeholders
Use simple analogies ("slow query = finding one book in an unsorted library vs. a catalogued one"). Focus on business impact: time saved, cost reduced, risk avoided. Use diagrams. Avoid jargon. Confirm they understood before moving on.
Back to questions9. Most Challenging Task
Pick a real example with genuine complexity. Cover: the specific technical challenge → constraints you were working under → the approach you chose and why → what the outcome was → what you'd do differently. Show ownership.
Back to questions10. End-to-End Project
Cover: problem it solves → architecture and tech stack choices (and why) → biggest technical challenges → how you handled performance → deployment and monitoring → team structure → what you'd improve now.
Back to questions11. Angular to React Migration
Why: better developer ecosystem, component model, hooks simplicity, team hiring pool. Challenges: migrating incrementally (micro-frontend boundary between Angular and React), retraining team, re-implementing routing/state management, regression testing.
Back to questions12. Team Conflicts
First understand their constraint (designers optimize for UX, backend for reliability — both valid). Find the shared goal. Propose a solution that addresses both concerns. Back proposals with data. If still stuck, involve a PM or tech lead as neutral mediator.
Back to questionsGood luck with your interviews! 🚀
Post a Comment