Skip to content

Easy Full Stack with Node.js Interview Questions

63 easy questions with answers. Definitions and fundamentals every candidate must answer quickly and correctly.

Topics in the easy set

Node.js Core and Event Loop: 12 Express.js Framework: 11 Asynchronous JavaScript: 8 Databases: MongoDB, SQL and Redis: 7 Testing and Debugging: 7 REST API Design: 6 Authentication and Security: 6 Deployment, Scaling and Performance: 6
Solved — easyStart 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

What is Node.js and why is it used for backend development?

Save to ▾
Show answer
Node.js is a JavaScript runtime built on the V8 engine that runs JavaScript outside the browser. It uses a single-threaded event loop with non-blocking I/O, so one process can handle thousands of concurrent connections cheaply. It is popular for APIs, real-time apps and microservices because teams can use one language across frontend and backend and reuse a huge npm ecosystem.
02

What is the difference between CommonJS and ES Modules in Node.js?

Save to ▾
Show answer
CommonJS uses require and module.exports, loads modules synchronously and was Node's original system. ES Modules use import and export, are statically analysable, support top-level await and are the JavaScript standard. In Node you enable ESM with the .mjs extension or "type": "module" in package.json. ESM can import CommonJS, but CommonJS needs dynamic import() to load ESM in older versions.
03

What are streams in Node.js and what types exist?

Save to ▾
Show answer
Streams process data in chunks instead of loading everything into memory. There are four types: Readable (fs.createReadStream, HTTP request), Writable (fs.createWriteStream, HTTP response), Duplex (TCP socket, both read and write) and Transform (zlib gzip, modifies data as it passes). Streams keep memory flat when serving large files, uploading media or processing big CSV logs.
04

What is the Buffer class in Node.js?

Save to ▾
Show answer
Buffer represents a fixed-length sequence of raw bytes stored outside the V8 heap. It is used for binary data such as files, images, TCP packets and crypto output. You create one with Buffer.from('text') or Buffer.alloc(size) and convert with toString('utf8' or 'base64'). Buffer.allocUnsafe is faster but may contain old memory, so fill it before use.
05

What is the EventEmitter and how do you use it?

Save to ▾
Show answer
EventEmitter from the events module implements the publish-subscribe pattern. Objects register listeners with on or once and trigger them with emit. Streams, HTTP servers and sockets all extend it. Always handle the 'error' event, because an emitted error without a listener crashes the process. Watch for memory leaks when listeners are added repeatedly; Node warns after 10 listeners by default.
06

Write a simple custom EventEmitter usage for an order service.

Save to ▾
Show answer
const EventEmitter = require('events'); class OrderService extends EventEmitter { place(order) { // save order... this.emit('placed', order); } } const svc = new OrderService(); svc.on('placed', (o) => console.log('Send email for', o.id)); svc.once('placed', () => console.log('First order today')); svc.on('error', (err) => console.error(err)); svc.place({ id: 101 });
07

Create a basic HTTP server in Node.js without any framework.

Save to ▾
Show answer
const http = require('http'); const server = http.createServer((req, res) => { if (req.method === 'GET' && req.url === '/health') { res.writeHead(200, { 'Content-Type': 'application/json' }); return res.end(JSON.stringify({ status: 'ok' })); } res.writeHead(404); res.end('Not found'); }); server.listen(3000, () => console.log('Listening on 3000'));
08

What is package.json and what is the difference between dependencies and devDependencies?

Save to ▾
Show answer
package.json describes a project: name, version, scripts, entry point and dependencies. dependencies are packages needed at runtime, such as express or mongoose. devDependencies are only for development and build, such as jest, eslint or nodemon. Running npm ci --omit=dev in production installs only runtime packages, which keeps Docker images smaller and reduces attack surface.
09

What is package-lock.json and why should it be committed?

Save to ▾
Show answer
package-lock.json records the exact resolved version and integrity hash of every installed package, including nested ones. Committing it makes installs reproducible across developer machines and CI, so a minor update in a transitive dependency cannot silently break production. In CI use npm ci, which installs strictly from the lock file and fails if it is out of sync with package.json.
10

Explain semantic versioning and the meaning of ^ and ~ in package.json.

Save to ▾
Show answer
Semantic versioning uses MAJOR.MINOR.PATCH: major for breaking changes, minor for new backward-compatible features, patch for bug fixes. A caret like ^4.18.2 allows any 4.x.x at or above 4.18.2. A tilde like ~4.18.2 allows only patch updates, 4.18.x. An exact version pins it. The lock file still decides what is actually installed.
11

A teammate uses fs.readFileSync inside an Express route. What is the problem and what would you suggest?

Save to ▾
Show answer
Synchronous file calls block the event loop for the whole read, so under load every request queues behind disk I/O and latency spikes. In a route, use fs.promises.readFile with await, or stream the file with fs.createReadStream and pipe it to the response. Sync calls are acceptable only at startup, for example reading a config file once before the server listens.
12

Tell me about a time you learned a new backend technology quickly to deliver a feature.

Save to ▾
Show answer
Situation: our team needed real-time order tracking and nobody had used WebSockets. Task: I owned the feature with a two-week deadline. Action: I spent two evenings on the Socket.IO docs, built a small prototype, shared a short demo with the team and then added rooms and Redis adapter for scaling. Result: we shipped on time, and I wrote an internal guide others reused.
13

What is a callback and what is callback hell?

Save to ▾
Show answer
A callback is a function passed to another function to run when an asynchronous task finishes, following Node's error-first convention (err, data). Callback hell is deeply nested callbacks where each async step depends on the previous one, making code hard to read, handle errors in and maintain. Promises and async/await flatten the nesting and centralise error handling with catch or try/catch.
14

What is a Promise and what are its states?

Save to ▾
Show answer
A Promise is an object representing the eventual result of an asynchronous operation. It has three states: pending, fulfilled with a value, or rejected with a reason. Once settled it never changes. You consume it with then, catch and finally, or with await. Promises chain, so returning a value or promise from then passes it to the next step.
15

How do you run async tasks in parallel versus in sequence?

Save to ▾
Show answer
// Sequential: each waits for the previous one for (const id of ids) { const user = await getUser(id); results.push(user); } // Parallel: start all, then wait together const users = await Promise.all(ids.map((id) => getUser(id))); // Use sequential only when steps depend on each other // or when you must limit load on a downstream service.
16

Why is using async callbacks inside forEach a common bug?

Save to ▾
Show answer
Array.forEach ignores the promise returned by an async callback, so it does not wait for any iteration and errors are not caught by the outer function. Code after the loop runs before the work is done. Use for...of with await for sequential processing, or map the items to promises and await Promise.all for parallel processing.
17

Convert this callback-based function to async/await: fs.readFile(path, 'utf8', (err, data) => {...}).

Save to ▾
Show answer
const fs = require('fs/promises'); async function readConfig(path) { try { const data = await fs.readFile(path, 'utf8'); return JSON.parse(data); } catch (err) { if (err.code === 'ENOENT') return {}; throw err; } } // Or wrap any callback API with util.promisify(fn).
18

What is a closure and how is it used in Node.js code?

Save to ▾
Show answer
A closure is a function that remembers variables from the scope where it was created, even after that outer function has returned. In Node it is used for middleware factories like rateLimit({ max: 100 }), private counters, memoisation and module-level state. A risk is memory leaks when closures hold large objects longer than needed, for example inside long-lived event listeners.
19

What is the difference between var, let and const?

Save to ▾
Show answer
var is function-scoped, hoisted and initialised as undefined, and can be redeclared. let and const are block-scoped and are in a temporal dead zone until declared, so accessing them early throws an error. const prevents reassignment of the binding but not mutation of an object's contents. Modern Node code uses const by default and let when reassignment is needed.
20

How do you explain asynchronous programming to a non-technical stakeholder or junior teammate?

Save to ▾
Show answer
I use a restaurant analogy. One waiter takes an order, gives it to the kitchen and serves other tables instead of waiting at the stove; when the dish is ready, the kitchen rings a bell. Node.js works the same: it starts a database or network task, handles other requests and resumes when the result is ready. Then I show a short code example with async and await.
21

What is Express.js and why is it widely used?

Save to ▾
Show answer
Express is a minimal, unopinionated web framework for Node.js that adds routing, middleware and helpers for requests and responses on top of the http module. It is widely used because it is simple, flexible and has a large ecosystem of middleware for logging, auth, validation and security. Many teams also use it as the base for frameworks like NestJS.
22

What is middleware in Express?

Save to ▾
Show answer
Middleware is a function with the signature (req, res, next) that runs during the request-response cycle. It can read or modify req and res, end the response, or call next() to pass control to the next middleware. Typical uses are parsing JSON, logging, authentication, CORS and rate limiting. Order matters, because middleware runs in the sequence it is registered.
23

What is the difference between app.use and app.get?

Save to ▾
Show answer
app.use mounts middleware for all HTTP methods and matches any path that starts with the given prefix, for example app.use('/api', router). app.get registers a handler only for GET requests on an exact route pattern. Use app.use for cross-cutting concerns like parsing and auth, and method-specific functions such as get, post, put and delete for endpoints.
24

How do you use express.Router to organise routes?

Save to ▾
Show answer
// routes/users.js const router = require('express').Router(); router.get('/', listUsers); router.get('/:id', getUser); router.post('/', auth, createUser); module.exports = router; // app.js app.use(express.json()); app.use('/api/v1/users', require('./routes/users')); // Keeps each resource in its own module with its own middleware.
25

What is the difference between req.params, req.query and req.body?

Save to ▾
Show answer
req.params holds route parameters from the path, such as id in /users/:id. req.query holds query string values like ?page=2&sort=name, used for filtering and pagination. req.body holds the parsed request payload of POST, PUT or PATCH and needs a parser such as express.json(). All are user input and must be validated before use.
26

How do you enable CORS in an Express app and why is it needed?

Save to ▾
Show answer
Browsers block cross-origin requests unless the server sends CORS headers. Use the cors package: app.use(cors({ origin: ['https://app.example.com'], credentials: true })). Avoid origin '*' with credentials, and restrict methods and headers you allow. CORS is a browser protection, not a security layer for your API, so you still need authentication and authorisation.
27

What does helmet do in an Express application?

Save to ▾
Show answer
helmet is middleware that sets secure HTTP response headers. It adds Content-Security-Policy, Strict-Transport-Security, X-Content-Type-Options nosniff, frame protection and removes X-Powered-By, reducing risks like clickjacking, MIME sniffing and some XSS attacks. It is one line, app.use(helmet()), but CSP usually needs tuning so your frontend scripts and assets still load.
28

What is the difference between res.send, res.json and res.end?

Save to ▾
Show answer
res.send sends a response and sets Content-Type based on the argument: string as HTML, Buffer as binary, object as JSON. res.json always serialises to JSON and sets application/json, and respects app settings like json spaces. res.end ends the response with no extra processing, useful for empty responses such as 204. Call only one per request to avoid headers-already-sent errors.
29

What causes the error 'Cannot set headers after they are sent to the client'?

Save to ▾
Show answer
It happens when code tries to send a second response for the same request, for example calling res.json in a callback and then again later, or forgetting return after sending an error response, or calling next() after responding. Fix it by returning immediately after each res.send or res.json, and making sure each code path sends exactly one response.
30

A client reports that a large JSON POST request fails with 413 Payload Too Large. What do you do?

Save to ▾
Show answer
express.json() has a default body limit of 100 KB, so bigger payloads are rejected with 413. If the size is legitimate, raise it for that route only, for example express.json({ limit: '2mb' }), and check any proxy limit such as Nginx client_max_body_size. For very large data, switch to file upload to object storage or pagination instead of huge JSON bodies.
31

Describe a time you disagreed with a senior developer on a technical approach.

Save to ▾
Show answer
Situation: a senior wanted to store sessions in server memory for a new API. Task: I believed it would break when we scaled to multiple pods. Action: I prepared a short comparison, showed a demo where users were logged out after a restart, and suggested Redis sessions or JWT. Result: we agreed on Redis, and the senior asked me to document the decision for the team.
32

What is a REST API and what are its key constraints?

Save to ▾
Show answer
REST is an architectural style where resources are identified by URLs and manipulated through standard HTTP methods. Key constraints: client-server separation, statelessness so each request carries all needed information, cacheable responses, uniform interface, layered system and optionally code on demand. In practice it means resource-based URLs, correct methods and status codes, and JSON representations.
33

Explain the main HTTP methods and which are idempotent.

Save to ▾
Show answer
GET reads a resource, POST creates or triggers an action, PUT replaces a resource fully, PATCH updates part of it and DELETE removes it. GET, PUT, DELETE, HEAD and OPTIONS are idempotent, meaning repeating the request has the same effect as doing it once. POST and usually PATCH are not, which is why payment APIs use idempotency keys for POST.
34

Which HTTP status codes should a REST API commonly return?

Save to ▾
Show answer
200 OK for successful reads and updates, 201 Created with a Location header for new resources, 204 No Content for deletes. 400 for invalid input, 401 when not authenticated, 403 when authenticated but not allowed, 404 not found, 409 conflict such as a duplicate email, 422 for validation errors in some APIs, 429 rate limited, 500 server error and 503 unavailable.
35

What is the difference between PUT and PATCH?

Save to ▾
Show answer
PUT replaces the entire resource with the representation sent, so missing fields may be reset; it is idempotent. PATCH applies a partial update, sending only changed fields, such as { "phone": "..." }. PATCH is more efficient for large objects. With JSON Merge Patch, repeated identical PATCH requests are effectively idempotent, but operations like increment are not.
36

How do you design good REST endpoint URLs?

Save to ▾
Show answer
Use plural nouns for resources and let methods express the action: GET /users, POST /users, GET /users/42, PATCH /users/42. Nest only for clear ownership, like GET /users/42/orders, and avoid deep nesting. Use lowercase kebab-case, query parameters for filtering, sorting and pagination, and version the API, for example /api/v1. Avoid verbs like /getUsers.
37

How do you document a REST API?

Save to ▾
Show answer
Use the OpenAPI 3 specification, written by hand in YAML or generated from code or validation schemas, and serve it with Swagger UI or Redoc. Document each endpoint's parameters, request and response schemas, status codes, auth and examples. Keep it in the repo, validate it in CI and generate client SDKs or contract tests from it so docs never drift from the code.
38

What is the difference between authentication and authorisation?

Save to ▾
Show answer
Authentication verifies who the user is, for example by checking a password, OTP or OAuth login. Authorisation decides what that verified user is allowed to do, such as whether they can delete an order or view admin reports. In an API, authentication failures return 401 and authorisation failures return 403. Both must be enforced on the server, never only in the frontend.
39

What is a JWT and what are its three parts?

Save to ▾
Show answer
A JSON Web Token is a compact, signed token used to carry claims between parties. It has three Base64URL parts separated by dots: header (algorithm and type), payload (claims like sub, role, exp) and signature. The signature proves the token was issued by the server and not modified. The payload is only encoded, not encrypted, so never put secrets in it.
40

How should passwords be stored in a database?

Save to ▾
Show answer
Never store plain text or use fast hashes like MD5 or SHA-256 alone. Use a slow, salted password hashing algorithm such as bcrypt with a cost factor around 10 to 12, or Argon2id, which is the current recommendation. The library generates a unique salt per password. On login, compare using the library's compare function, which is timing-safe.
41

What is SQL injection and how do you prevent it in Node.js?

Save to ▾
Show answer
SQL injection happens when user input is concatenated into a query, letting attackers change it, for example ' OR 1=1 --. Prevent it with parameterised queries, such as pool.query('SELECT * FROM users WHERE email = $1', [email]) in pg, or an ORM like Prisma or Sequelize that parameterises automatically. Also validate input and give the database user minimum privileges.
42

How do you manage secrets such as database passwords and API keys in a Node.js app?

Save to ▾
Show answer
Never commit secrets to Git. Load them from environment variables, using a .env file only for local development and keeping it in .gitignore. In production, use a secrets manager such as AWS Secrets Manager, Azure Key Vault, HashiCorp Vault or Kubernetes secrets with encryption. Rotate keys regularly, scan repos with tools like gitleaks and validate required variables at startup.
43

How do you keep yourself updated about security best practices as a backend developer?

Save to ▾
Show answer
I follow the Node.js security release announcements and OWASP cheat sheets, read GitHub security advisories for packages we use and keep Dependabot alerts on. I also practise with labs like OWASP Juice Shop. In my last project I used this to propose helmet, rate limits and stricter input validation, and I shared a short security checklist that the team adopted in pull request reviews.
44

What is the difference between SQL and NoSQL databases?

Save to ▾
Show answer
SQL databases such as PostgreSQL and MySQL store data in tables with fixed schemas, support joins and strong ACID transactions, and suit relational data like orders and payments. NoSQL databases such as MongoDB, Redis or Cassandra use documents, key-value or wide-column models with flexible schemas and easier horizontal scaling. The choice depends on data relationships, consistency needs and query patterns.
45

What is Mongoose and why use it with MongoDB?

Save to ▾
Show answer
Mongoose is an ODM for MongoDB in Node.js. It adds schemas with types, validation, defaults, middleware hooks such as pre save, virtuals, population of references and a convenient query API. This brings structure to schemaless MongoDB collections and reduces bugs. For very high-performance or simple cases, some teams use the native MongoDB driver directly to avoid the overhead.
46

Define a Mongoose schema for a user with validation and an index.

Save to ▾
Show answer
const { Schema, model } = require('mongoose'); const userSchema = new Schema({ name: { type: String, required: true, trim: true }, email: { type: String, required: true, unique: true, lowercase: true }, password: { type: String, required: true, select: false }, role: { type: String, enum: ['user', 'admin'], default: 'user' }, city: String }, { timestamps: true }); userSchema.index({ city: 1, createdAt: -1 }); module.exports = model('User', userSchema);
47

What is an index and how does it improve query performance?

Save to ▾
Show answer
An index is a data structure, usually a B-tree, that lets the database find rows without scanning the whole table or collection. Indexes speed up reads on filtered, sorted and joined fields but slow down writes and use storage. Create them based on real query patterns, check usage with EXPLAIN or explain('executionStats'), and remove unused ones.
48

Explain ACID properties of a database transaction.

Save to ▾
Show answer
Atomicity means all operations in a transaction succeed or none do. Consistency means the database moves from one valid state to another, respecting constraints. Isolation means concurrent transactions do not see each other's partial work, controlled by isolation levels. Durability means committed data survives crashes. Money transfers rely on ACID so a debit never happens without the matching credit.
49

Write a parameterised query with node-postgres to fetch a user's recent orders.

Save to ▾
Show answer
const { Pool } = require('pg'); const pool = new Pool({ connectionString: process.env.DATABASE_URL, max: 10 }); async function recentOrders(userId, limit = 10) { const { rows } = await pool.query( `SELECT id, amount, status, created_at FROM orders WHERE user_id = $1 ORDER BY created_at DESC LIMIT $2`, [userId, limit] ); return rows; }
50

What is Redis and how is it used with Node.js backends?

Save to ▾
Show answer
Redis is an in-memory key-value store with data types like strings, hashes, lists, sets, sorted sets and streams. Node apps use it for caching database results, session storage, rate limiting counters, distributed locks, leaderboards, pub/sub between instances and job queues through BullMQ. Data lives in memory, so use TTLs and eviction policies and do not treat it as the only copy of important data.
51

What is the difference between unit, integration and end-to-end tests for a Node.js API?

Save to ▾
Show answer
Unit tests check a single function or service in isolation with dependencies mocked; they are fast and numerous. Integration tests check several parts together, such as a route, service and a real test database. End-to-end tests run the full system like a user would, often through HTTP against a deployed environment. A healthy test pyramid has many unit tests and fewer E2E tests.
52

Write a Jest unit test for a function that calculates order total with GST.

Save to ▾
Show answer
// pricing.js const total = (items, gst = 0.18) => Math.round(items.reduce((s, i) => s + i.price * i.qty, 0) * (1 + gst) * 100) / 100; module.exports = { total }; // pricing.test.js const { total } = require('./pricing'); describe('total', () => { it('adds 18% GST by default', () => { expect(total([{ price: 100, qty: 2 }])).toBe(236); }); it('returns 0 for an empty cart', () => { expect(total([])).toBe(0); }); });
53

How do you debug a Node.js application?

Save to ▾
Show answer
Start Node with --inspect or --inspect-brk and attach Chrome DevTools at chrome://inspect or the VS Code debugger to set breakpoints, step through code and inspect variables. Use structured logs with request IDs to trace issues in deployed environments. For async issues, check stack traces with async context, and for performance use --cpu-prof or clinic.js flame graphs.
54

Why is structured logging important and which libraries are used?

Save to ▾
Show answer
Structured logs are JSON lines with fields like level, timestamp, requestId, userId and message, so tools like ELK, Loki, Datadog or CloudWatch can search and aggregate them. pino is fast and popular, winston is flexible with many transports. Log at correct levels, include a correlation ID per request, and never log passwords, tokens, full card numbers or Aadhaar numbers.
55

What is code coverage and is 100 percent coverage a good goal?

Save to ▾
Show answer
Code coverage measures how much code tests execute: lines, branches, functions and statements, reported by Jest with --coverage or c8. It shows untested areas but not whether assertions are meaningful. Chasing 100 percent leads to brittle tests of trivial code. A practical target is around 70 to 85 percent with strong coverage of business logic, error paths and security checks.
56

A new developer pushes code that breaks the login API in staging. How would you prevent this in future?

Save to ▾
Show answer
Add automated checks before merge: unit and integration tests for login in the CI pipeline, branch protection requiring green builds and at least one review, linting and type checks. Add a smoke test that runs after each staging deploy and alerts on failure. Treat it as a blameless learning moment and pair with the developer to write the missing tests.
57

How do you handle a situation where you cannot find the root cause of a bug before a deadline?

Save to ▾
Show answer
I inform my lead early with what I know, what I have ruled out and the risk. I propose a safe mitigation, such as a feature flag to disable the path or a rollback, and add extra logging to capture more data. In one case this let us release on time with the feature off, and the new logs revealed the cause two days later.
58

What is PM2 and when do you need it?

Save to ▾
Show answer
PM2 is a process manager for Node.js on virtual machines. It keeps apps running and restarts them on crashes, runs cluster mode across CPU cores, supports zero-downtime reloads, log management and startup scripts. In Docker or Kubernetes you usually do not need PM2, because the orchestrator restarts containers and you scale with replicas, so you run node directly.
59

Why put Nginx in front of a Node.js application?

Save to ▾
Show answer
Nginx acts as a reverse proxy: it terminates TLS, serves static files efficiently, compresses responses, buffers slow clients, load balances across multiple Node instances and adds rate limiting and request size limits. This frees Node to focus on application logic. On cloud platforms a managed load balancer or ingress controller often plays the same role.
60

What are common ways to deploy a Node.js API in 2026?

Save to ▾
Show answer
Options include virtual machines like EC2 with PM2 and Nginx, containers on Kubernetes such as EKS, AKS or GKE, managed container services like AWS ECS Fargate, Cloud Run or Azure Container Apps, platforms like Render or Railway, and serverless functions on AWS Lambda. Choice depends on traffic patterns, team skills, cost and need for control.
61

Write a simple Docker Compose file to run a Node API with MongoDB and Redis locally.

Save to ▾
Show answer
services: api: build: . ports: ['3000:3000'] environment: MONGO_URL: mongodb://mongo:27017/app REDIS_URL: redis://redis:6379 depends_on: [mongo, redis] mongo: image: mongo:7 volumes: ['mongo-data:/data/db'] redis: image: redis:7-alpine volumes: mongo-data:
62

How do you manage configuration for dev, staging and production environments?

Save to ▾
Show answer
Follow the twelve-factor approach: keep config in environment variables, not code. Load and validate them at startup with a schema, for example zod or envalid, and fail fast if any are missing. Use .env files only locally, and store production values in the platform's secret store or config maps. Keep the same Docker image across environments and change only configuration.
63

Why do you want to work as a Node.js backend developer?

Save to ▾
Show answer
I enjoy building the systems behind products: APIs, data models and integrations. Node.js lets me use JavaScript across the stack and ship features quickly, and I like solving problems around performance and reliability. In my projects I built a REST API with authentication, MongoDB and Docker deployment, and I want to grow by working on real traffic and learning system design from experienced engineers.

Frequently asked questions

Who should practise easy Full Stack with Node.js questions?

Freshers and career switchers should start here, and experienced candidates should skim them the day before an interview.

How should I practise these?

Answer each question aloud before opening the answer, mark it as solved only when your answer matches the key idea, and save misses to Last-Minute Revision.

Other difficulty levels