Node.js, Next.js and JavaScript Interview Questions 2026: Freshers to 10 Years, Answers and Round Pattern
JavaScript, Node.js and Next.js interview guide: the round pattern, core JS and event loop questions with expected answers, Express and API design, Next.js App Router, React basics, performance, system design and coding problems.
How to use this guide
This guide covers JavaScript, Node.js and Next.js from the basics to production questions. Each section has the question, the answer you should be able to give, and the reason behind it. Read the answer, then say it aloud in your own words. Interviewers reward clear reasoning more than a memorised paragraph.
The questions are the kind that appear in frontend, backend and full-stack rounds at service companies, product companies and startups. Exact questions differ by company and interviewer. The patterns repeat.
The guide does not claim to quote any particular candidate. The answers are standard, correct explanations that follow the official behaviour of the language and frameworks.
What the interview pattern usually looks like
Most JavaScript and full-stack loops have these rounds:
| Round | What is tested | Typical length |
|---|---|---|
| Online test or screening | Output prediction, short coding, basic DOM or Node questions | 30 to 60 minutes |
| JavaScript fundamentals | Closures, this, prototypes, event loop, promises | 45 minutes |
| Coding round | Array and string problems, async helpers, small utilities | 45 to 60 minutes |
| Framework round | React or Next.js, state, data fetching, rendering modes | 45 to 60 minutes |
| Backend or Node round | Express, middleware, auth, streams, error handling, database | 45 minutes |
| System design (experienced) | Architecture of a web app or API, caching, scaling | 45 to 60 minutes |
| Hiring manager | Project depth, trade-offs, ownership | 30 minutes |
Service companies lean on fundamentals and a coding test. Product companies ask more about system design, debugging and the reasons behind a choice. Startups often give a take-home task to build a small feature in Next.js or Express.
Level 1: JavaScript fundamentals
These questions are asked to almost every fresher and to many experienced candidates. Get them right first.
Q1. What is the difference between var, let and const?
var is function-scoped and is hoisted with the value undefined. let and const are block-scoped and are hoisted but not initialised, so using them before the declaration throws a ReferenceError (the temporal dead zone). const stops reassignment of the binding, but an object or array it holds can still change.
Q2. What is hoisting?
Declarations move to the top of their scope during compilation. Function declarations are fully hoisted. var declarations are hoisted and set to undefined. let and const are hoisted but stay uninitialised until the line runs.
console.log(a); // undefined
var a = 5;
console.log(b); // ReferenceError
let b = 5;
Q3. What is a closure? Give an example.
A closure is a function that keeps access to variables from the scope where it was created, even after that outer function has returned.
function makeCounter() {
let count = 0;
return function () {
count += 1;
return count;
};
}
const next = makeCounter();
next(); // 1
next(); // 2
Expected answer: count lives on after makeCounter returns, because the inner function closes over it. A common follow-up is the classic loop problem with var inside setTimeout, which let fixes because each iteration gets its own binding.
Q4. How does this work in JavaScript?
this depends on how a function is called, not where it is written:
- In a method call,
thisis the object before the dot. - In a plain function call,
thisisundefinedin strict mode and the global object otherwise. - With
new,thisis the newly created object. - Arrow functions do not have their own
this. They take it from the surrounding scope. call,applyandbindsetthisexplicitly.
Q5. What is the difference between == and ===?
== converts types before comparing. === compares without conversion. Use === by default. Know the classic traps: null == undefined is true, 0 == "" is true, [] == false is true.
Q6. What are the primitive types, and what does typeof null return?
The primitives are string, number, bigint, boolean, undefined, symbol and null. typeof null returns "object", a known bug kept for backward compatibility. Check for null with value === null.
Q7. What is the prototype chain?
Every object has an internal link to a prototype. When you read a property that the object does not own, JavaScript looks it up the chain until it finds it or reaches null. Classes are syntax over this prototype system.
Q8. What is the difference between a function declaration, a function expression and an arrow function?
Function declarations are hoisted fully. Function expressions and arrow functions are not hoisted in the same way. Arrow functions do not bind their own this, arguments or super, and they cannot be used as constructors.
Q9. What do map, filter and reduce do?
map returns a new array with each element transformed. filter keeps elements where the callback returns true. reduce folds the array into one value. Interviewers often ask you to write reduce from scratch, for example to group items by a key.
Q10. What is destructuring and spread?
Destructuring pulls values out of arrays or objects into variables. Spread expands an iterable or object into individual elements. Both are used for immutable updates in React state:
const next = { ...user, name: "Asha" };
const [first, ...rest] = items;
Q11. What is the difference between null and undefined?
undefined means a variable has been declared but not given a value, or a function returned nothing. null is an assigned value meaning "no value". JSON cannot represent undefined, so it is dropped from objects when serialised.
Q12. What are default parameters and rest parameters?
Default parameters give a value when the argument is missing. Rest parameters collect the remaining arguments into an array. Rest parameters replaced the older arguments object in modern code.
Level 2: The event loop and async code
This is the most important topic for Node.js and a common trap in every JavaScript round.
Q13. Explain the event loop.
JavaScript runs on one thread with one call stack. When an asynchronous operation finishes, its callback waits in a queue. The event loop takes a callback from the queue only when the call stack is empty.
+-------------------+
| Call stack | <- runs synchronous code
+---------+---------+
|
+---------v---------+ +----------------------+
| Event loop | <---- | Microtask queue | promises, queueMicrotask
+---------+---------+ +----------------------+
| +----------------------+
+---------------> | Macrotask queue | timers, I/O, setImmediate
+----------------------+
Rule to state in an interview: after each macrotask, the runtime drains the entire microtask queue before the next macrotask starts.
Q14. What is the output of this code, and why?
console.log("1");
setTimeout(() => console.log("2"), 0);
Promise.resolve().then(() => console.log("3"));
console.log("4");
Output is 1, 4, 3, 2. The synchronous logs run first. The promise callback is a microtask and runs before the timer, which is a macrotask, even with a delay of zero.
Q15. What is the difference between promises and async/await?
async/await is syntax over promises. An async function always returns a promise. await pauses that function until the promise settles, without blocking the thread. Errors from awaited promises are caught with try/catch.
Q16. How do Promise.all, Promise.allSettled, Promise.race and Promise.any differ?
Promise.allresolves when all promises resolve, and rejects on the first rejection.Promise.allSettledwaits for all and reports each outcome. It never rejects.Promise.racesettles with the first promise to settle, either way.Promise.anyresolves with the first success and rejects only if all fail, with anAggregateError.
Q17. A loop calls await on each item. Why is it slow, and how do you fix it?
Sequential await inside a for loop waits for each call before starting the next. If the calls are independent, start them together:
// slow: one after another
for (const id of ids) {
results.push(await fetchUser(id));
}
// faster: all at once
const results = await Promise.all(ids.map((id) => fetchUser(id)));
Mention the trade-off: Promise.all can flood a downstream service, so limit concurrency for large lists.
Q18. What is a memory leak in JavaScript, and what causes one?
Common causes are event listeners that are never removed, timers that keep references, closures that hold large objects, and global caches that grow without a limit. Use the browser or Node heap snapshot to find retained objects.
Q19. What is debouncing and throttling?
Debouncing waits until calls stop for a set time, then runs once. Throttling runs at most once per time window. Use debounce for search input and throttle for scroll handlers.
Level 3: Node.js runtime and Express
Q20. What is Node.js, and how is it different from the browser JavaScript runtime?
Node.js runs JavaScript on the server, using the V8 engine and the libuv library for asynchronous I/O. It has no DOM. It adds file system, network, process and streams APIs. It is single-threaded for JavaScript, but I/O runs in the background through libuv and the OS.
Q21. What is the difference between process.nextTick, setImmediate and setTimeout?
process.nextTick callbacks run right after the current operation, before promise microtasks. setImmediate runs in the check phase of the event loop. setTimeout runs in the timers phase after its delay. Mention that the order of setTimeout(0) and setImmediate inside the main module can vary, but inside an I/O callback setImmediate always runs first.
Q22. What are streams, and why use them?
Streams process data in chunks, so a large file does not need to fit in memory. Node has readable, writable, duplex and transform streams. Use pipeline (from stream/promises) to connect streams and handle errors correctly.
import { pipeline } from "node:stream/promises";
import { createReadStream, createWriteStream } from "node:fs";
import { createGzip } from "node:zlib";
await pipeline(
createReadStream("big.log"),
createGzip(),
createWriteStream("big.log.gz"),
);
Q23. When do you use cluster or worker_threads?
cluster starts several Node processes that share a port, to use multiple CPU cores for request handling. worker_threads runs CPU-heavy JavaScript in parallel threads inside one process. Neither is needed for I/O-bound work, which the event loop already handles.
Q24. How does middleware work in Express?
Middleware is a function with the signature (req, res, next). It runs in the order it is registered, and each one must end the response or call next(). Error-handling middleware has four arguments (err, req, res, next) and is registered last.
app.use(express.json());
app.use((err, req, res, next) => {
const status = err.status ?? 500;
res.status(status).json({ message: err.expose ? err.message : "Server error" });
});
Q25. How do you handle errors in async Express routes?
Express 4 does not catch rejected promises from async route handlers. Wrap them in a helper, or use Express 5, which forwards rejections to the error middleware. Never let a rejection escape without a handler, because it crashes the process on newer Node versions.
Q26. How would you authenticate an API?
Typical answer: a short-lived access token (JWT) signed by the server, sent in the Authorization header, plus a refresh token stored in an HTTP-only cookie. Verify the signature and expiry on each request. Store passwords with a slow hash such as bcrypt or argon2, never in plain text. Mention the trade-off: stateless JWTs are hard to revoke, so a session store or a token blocklist is used when you need instant logout.
Q27. How do you validate request input?
Use a schema validator such as Zod, Joi or Yup at the route boundary. Reject bad input with status 400 and a clear message. Never trust req.body shape or types without validating.
Q28. What is the difference between REST and GraphQL, and when would you pick GraphQL?
REST exposes resources at URLs with HTTP verbs. GraphQL exposes one endpoint where the client asks for exactly the fields it needs. GraphQL helps when many clients need different shapes of the same data. REST is simpler for caching and for public APIs.
Q29. How do you handle environment variables and secrets in Node?
Read them from process.env, load local values from a .env file in development only, and never commit .env. In production, inject secrets through the platform or a secret manager. Fail fast on startup if a required variable is missing.
Level 4: React essentials
Most Next.js roles expect solid React. These questions are asked in almost every frontend round.
Q30. What is the difference between state and props?
Props are inputs passed from a parent and are read-only for the child. State is data owned by a component that changes over time and triggers a re-render when it changes.
Q31. How does useEffect work, and what is the dependency array for?
useEffect runs side effects after render. The dependency array tells React when to run the effect again. An empty array runs once after mount. Omitting the array runs after every render. Missing dependencies cause stale values and are the most common bug in interviews.
Q32. What does useMemo and useCallback do, and when do they help?
useMemo caches the result of a computation between renders. useCallback caches a function identity. They help when a child is wrapped in React.memo and receives a function or object prop, or when a computation is expensive. Using them everywhere adds overhead and hides the real problem.
Q33. Why do we need keys in lists?
Keys let React match list items between renders. Use a stable unique id, not the array index, when items can be reordered, added or removed. Index keys break state in inputs inside the list.
Q34. What is the virtual DOM, and is it always faster?
The virtual DOM is an in-memory tree of elements. React diffs the new tree against the old one and applies only the changes to the real DOM. It is not inherently faster than direct DOM updates. Its benefit is predictable updates from declarative code.
Q35. How would you manage global state?
Start with local state and lift it up when needed. Use context for values that change rarely, such as theme or the current user. Use a store library such as Zustand or Redux Toolkit for frequent global updates. For server data, use a data-fetching library such as TanStack Query, or server components in Next.js, rather than copying server data into a global store.
Level 5: Next.js App Router
The App Router is the default in Next.js 13 and later, and most current projects use it. Know both the App Router and the older Pages Router, because many codebases still run on Pages.
Q36. What is the difference between the App Router and the Pages Router?
The App Router uses the app/ directory, nested layouts, React Server Components by default, streaming with loading.tsx and Suspense, and route handlers in route.ts. The Pages Router uses pages/, getServerSideProps and getStaticProps, and treats all components as client-side by default for data fetching. New projects should use the App Router.
Q37. What is a Server Component, and what is a Client Component?
Server Components render on the server and send HTML and serialised data, with no JavaScript bundle for that component. They can read databases and secrets directly. Client Components are marked with "use client". They run in the browser and can use state, effects and browser APIs. Keep the client boundary as low in the tree as you can.
Q38. What is the difference between SSR, SSG and ISR?
- SSG (static site generation) builds HTML at build time. Fastest to serve, data is fixed until the next build.
- SSR (server-side rendering) builds HTML per request. Fresh data, slower than static.
- ISR (incremental static regeneration) serves static pages and rebuilds them in the background after a set time or on demand with revalidation.
In the App Router, a route is static unless it uses dynamic functions such as cookies(), headers() or uncached data.
Q39. How does caching work in the App Router?
Next.js caches fetch responses, full routes and data by default in different layers. Control this with the cache option, the revalidate time, and revalidatePath or revalidateTag after a mutation. Version-specific defaults changed between Next.js 14 and 15, so state the version when you answer and say how you would check the behaviour in the docs for that version.
Q40. What are Server Actions?
Server Actions are async functions marked with "use server" that run on the server and can be called from forms or client code. They handle mutations without a separate API route. Validate their input on the server, because the client can call them with any payload.
// app/actions.ts
"use server";
export async function saveNote(formData: FormData) {
const text = String(formData.get("text") ?? "").trim();
if (!text) throw new Error("Empty note");
await db.note.create({ data: { text } });
}
Q41. What is the difference between a layout, a template and a page?
A layout wraps child routes and keeps its state across navigations. A template also wraps children but re-mounts on each navigation. A page is the route's UI. Use loading.tsx for instant loading states and error.tsx for error boundaries per segment.
Q42. What does middleware do in Next.js?
Middleware runs before a request reaches the route. It is used for redirects, rewrites, A/B flags and simple auth checks. Keep it light, because it runs on every matched request. Do not query the database in it.
Q43. What is hydration, and what goes wrong with it?
Hydration attaches event handlers to HTML the server sent. A mismatch happens when the server HTML differs from the first client render, for example because of Date.now(), Math.random() or browser-only code. Fix it by moving that logic into an effect or a client component.
Q44. How do you read and write route parameters and search parameters?
Dynamic segments use folders such as app/blog/[slug]/page.tsx. Read them from the params prop. Search parameters come through searchParams. In Next.js 15, params and searchParams are async and must be awaited. Mention the version difference if you know it.
Q45. How do you optimise images and fonts?
Use the next/image component for automatic sizing, lazy loading and modern formats. Use next/font to self-host fonts and avoid layout shift. Set priority on the hero image that is above the fold.
Level 6: Performance and production
Q46. How would you find why a page is slow?
Start with measurement, not guesses. Use the browser performance panel and Lighthouse for Core Web Vitals: LCP, INP and CLS. On the server, log request duration, use profiling tools and check slow database queries. Then fix the largest cost first.
Q47. How do you reduce JavaScript bundle size?
Move work to the server with Server Components. Use dynamic imports for heavy components. Remove unused dependencies and check with a bundle analyser. Import only the function you need from large libraries.
Q48. What is the difference between CPU-bound and I/O-bound work in Node?
I/O-bound work waits on disk, network or database, and the event loop handles many waits at once. CPU-bound work such as image processing or large JSON parsing blocks the loop. Move CPU work to a worker thread, a queue or a separate service.
Q49. How do you handle logging and monitoring for a Node service?
Use structured logs in JSON with request ids. Track error rates, latency percentiles and event loop lag. Alert on symptoms users feel, such as error rate and p95 latency, not only on CPU.
Q50. What is a common cause of a Node process crashing in production?
An unhandled promise rejection or an uncaught exception. Handle errors where they occur, and add process-level handlers only for logging and a controlled shutdown. Restart the process with a supervisor or the platform, not by ignoring the error.
Q51. How do you test a Node or Next.js app?
Unit tests with Jest or Vitest for pure functions. API tests with Supertest or a similar tool for Express routes. Component tests with React Testing Library. End-to-end tests with Playwright for critical user flows. Mock the network at the boundary, not inside the code under test.
Level 7: System design for web backends
Experienced candidates are asked to design a feature or a service. Use this order: requirements, data model, API, caching, scaling, failure handling.
Q52. Design a URL shortener using Node.js.
Requirements: create short links, redirect fast, track clicks. Data model: id, short_code (unique index), target_url, created_at. API: POST /links, GET /:code returns a redirect. Scale: most traffic is reads, so cache hot codes in Redis with a TTL. Generate codes from a counter encoded in base62, not random strings with collision checks. Track clicks asynchronously through a queue, so the redirect path stays fast.
Q53. How would you add rate limiting to an API?
Use a token bucket or fixed window counter stored in Redis, keyed by user id or IP. Return status 429 with a Retry-After header. Apply stricter limits to login and password reset routes. Note the trade-off: IP-based limits can block users behind a shared network.
Q54. How would you structure a Next.js project for a large team?
Group by feature, not by file type. Keep data access in server modules. Put shared UI in a components folder. Use route groups for layout boundaries. Put all environment access in one module that validates values at startup.
Q55. How do you handle file uploads in a Node API?
Do not stream large uploads through the app server if you can avoid it. Issue a pre-signed URL from the server and let the client upload directly to object storage. Store the object key in the database after the upload completes. Validate type and size on the server and scan files if users can share them.
Coding questions asked in JS rounds
Write these by hand without an editor. Say the approach and the complexity before you code.
C1. Implement debounce.
function debounce(fn, wait) {
let timer;
return function (...args) {
clearTimeout(timer);
timer = setTimeout(() => fn.apply(this, args), wait);
};
}
C2. Implement a Promise.all from scratch.
function promiseAll(items) {
return new Promise((resolve, reject) => {
const results = new Array(items.length);
let done = 0;
if (items.length === 0) return resolve(results);
items.forEach((item, i) => {
Promise.resolve(item).then((value) => {
results[i] = value;
done += 1;
if (done === items.length) resolve(results);
}, reject);
});
});
}
Expected points: keep the input order, handle an empty array, and reject on the first error.
C3. Deep clone an object, handling arrays, dates and cycles.
Use structuredClone(value) in modern runtimes. In an interview, also explain how you would write it by hand: recurse on objects and arrays, copy Date with new Date(value), and keep a WeakMap of seen objects to handle cycles.
C4. Flatten a nested array to a given depth.
function flatten(arr, depth = 1) {
return depth > 0
? arr.reduce((acc, item) => acc.concat(Array.isArray(item) ? flatten(item, depth - 1) : item), [])
: arr.slice();
}
C5. Build an LRU cache with get and put in O(1).
Use a Map, which keeps insertion order. On get, delete the key and re-insert it to mark it recent. On put, if the size exceeds the capacity, delete the first key, which is the oldest.
class LRUCache {
constructor(capacity) {
this.capacity = capacity;
this.map = new Map();
}
get(key) {
if (!this.map.has(key)) return -1;
const value = this.map.get(key);
this.map.delete(key);
this.map.set(key, value);
return value;
}
put(key, value) {
if (this.map.has(key)) this.map.delete(key);
this.map.set(key, value);
if (this.map.size > this.capacity) {
this.map.delete(this.map.keys().next().value);
}
}
}
C6. Write a simple event emitter with on, off and emit.
Store listeners in a Map from event name to a Set of functions. on adds, off removes, and emit calls each listener with the arguments. Mention that a production emitter must guard against a listener removing itself while the list is being iterated, so copy the set before the loop.
C7. Group an array of objects by a key using reduce.
const groupBy = (items, key) =>
items.reduce((acc, item) => {
(acc[item[key]] ||= []).push(item);
return acc;
}, {});
How to answer 'explain a project'
Most framework rounds start with your project. Prepare a three-minute walk-through:
- The problem and the user. One sentence.
- Your role and the part you built, named clearly.
- The stack and why you chose it. Give one trade-off you accepted.
- One hard bug or performance issue, with the cause and the fix.
- What you would change now.
Interviewers test depth with follow-up questions. Only list a technology if you can explain how it works under the hood.
Common mistakes
- Guessing the output of a snippet without reasoning. Say the order out loud. Microtasks before timers is the classic check.
- Using index keys in dynamic lists. It breaks inputs and state.
- Putting every component in client mode. It sends more JavaScript and slows the first load.
- Using
awaitin a loop for independent calls. UsePromise.allwhere it is safe. - Catching errors and ignoring them. Log them and return a clear response.
- Confusing Next.js versions. Name the version you are answering for, and check the docs for caching defaults.
A four-week preparation plan
| Week | Focus | Output |
|---|---|---|
| 1 | Closures, this, prototypes, promises, event loop | Predict ten output snippets with reasons |
| 2 | Node runtime, streams, Express, auth, validation | Build a small REST API with tests |
| 3 | React hooks, Next.js App Router, caching, Server Actions | Rebuild one page with server data and a form |
| 4 | Coding rounds, performance, system design, project story | Solve C1 to C7 from memory, write your project talk |
Frequently asked questions
Is TypeScript needed? Most Next.js jobs expect TypeScript now. Learn the basic types, generics and how to type props and API responses.
Should I learn NestJS? Learn Express first, then NestJS if the target companies use it. The ideas, such as modules, dependency injection and middleware, carry over.
What if I do not have a production project? Build one small full-stack app with auth, a database, tests and deployment. Explain the trade-offs you made. That is a stronger answer than a long list of tutorials.
Frequently Asked Questions
For frontend and full-stack roles, yes. Most product teams in India use Next.js or a similar framework. Learn the App Router, server and client components, data fetching and caching first.
Closures, the event loop, promises and async/await, and the difference between var, let and const. Expect at least one question that asks you to predict the output of a snippet.
Node.js with Express or NestJS is enough for many backend roles. You also need a database, authentication, testing and deployment basics.
Say what you know, reason out loud, and state the assumption. Interviewers grade the reasoning more than a memorised line.
Four weeks at one to two hours a day is enough for a fresher with basic JavaScript. Experienced developers should focus on the system design and production sections.
Keshav founded StudentUpdate.in and edits every recruitment notice, syllabus page and practice set the site publishes. Each notice is read from the issuing body's PDF or portal before it goes live; dates, fees, vacancy tables and eligibility rules are copied from that document, not from other websites.