Skip to content

Full Stack with Node.js Interview Questions for 7 Years Experience

40 questions with answers for candidates with 7 years of experience — 1 easy, 19 medium, 20 hard.

What interviewers expect: 7 years experience

Seven-year candidates are evaluated as senior engineers or tech leads. Interviews include complex system design, cross-team technical decisions, migration strategies such as monolith to microservices, cost and reliability trade-offs and security architecture. Behavioural rounds test conflict handling, influencing without authority and delivery under pressure. Prepare clear stories with measurable impact on performance, reliability or developer productivity.

This set is weighted towards Deployment, Scaling and Performance (8), Authentication and Security (7), REST API Design (7), Testing and Debugging (6).

Architecture decisions Migration strategy Reliability and cost Technical leadership
Solved at this levelStart practicing
3 QUESTIONS FREESign up to unlock the full question bank and track your progress.Unlock every question and answer, then continue practising company-wise and package-wise.
3 questions free Unlock the rest in seconds
01

What is the difference between throwing an error and rejecting a promise inside an async function?

Save to ▾
Show answer
Inside an async function they behave the same: throw new Error() causes the returned promise to reject with that error. Outside async functions, a throw inside a plain callback such as setTimeout is not caught by promise handlers and becomes an uncaught exception. Always reject with Error objects, not strings, so you keep a stack trace.
02

A security audit finds that users can see other users' orders by changing the order ID in the URL. How do you fix it?

Save to ▾
Show answer
This is broken object level authorisation. Every query must be scoped to the authenticated user: Order.findOne({ _id: id, userId: req.user.id }), returning 404 if not found. Put this check in a shared service or middleware so no route can skip it, add tests that try other users' IDs, and consider non-guessable IDs like UUIDs as defence in depth, not as the fix.
03

Write a centralised error handler with a custom AppError class.

Save to ▾
Show answer
class AppError extends Error { constructor(message, status = 500) { super(message); this.status = status; } } app.use((err, req, res, next) => { const status = err.status || 500; logger.error({ err, path: req.path }); res.status(status).json({ error: status === 500 ? 'Internal server error' : err.message }); }); // In a route: throw new AppError('User not found', 404);
04

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.
05

How do you achieve zero-downtime deployments for a Node.js service?

Save to ▾
Show answer
Use rolling or blue-green deployments so new instances start and pass readiness checks before old ones are removed. Implement graceful shutdown on SIGTERM so in-flight requests finish. Keep database migrations backward compatible using expand and contract. Use feature flags for risky changes and have automated rollback on error rate spikes. Canary releases send a small share of traffic first.
06

What is contract testing and why is it useful for microservices?

Save to ▾
Show answer
Contract testing verifies that a provider API and its consumers agree on request and response formats without running the whole system. With Pact, the consumer writes expectations that become a contract, and the provider runs them in its own CI. It catches breaking changes like a renamed field before deployment, and is faster and less flaky than full end-to-end environments.
07

After a Node.js version upgrade, a few integration tests fail with date and crypto differences. How do you handle the upgrade safely?

Save to ▾
Show answer
Read the release notes and changelog for breaking changes, such as deprecated APIs, OpenSSL updates or changed default behaviour. Run the full test suite on the new version in a CI matrix alongside the old one, fix failures one by one and check native modules rebuild correctly. Roll out to staging, then to a canary in production while watching error rates before upgrading all services.
08

How do you optimise JSON serialisation for very large API responses?

Save to ▾
Show answer
Large JSON.stringify calls block the event loop. Reduce payload size with pagination and field selection first. For unavoidable large outputs, stream the response as NDJSON or a streamed JSON array, use schema-based fast serialisers like fast-json-stringify, which Fastify uses, and cache precomputed responses. Offload heavy transformation to worker threads or background jobs that write files to storage.
09

How do you serve a React build and an API from the same Express server?

Save to ▾
Show answer
const path = require('path'); app.use('/api', apiRouter); app.use(express.static(path.join(__dirname, 'client/dist'), { maxAge: '1y' })); // SPA fallback for client-side routes app.get(/^\/(?!api).*/, (req, res) => { res.sendFile(path.join(__dirname, 'client/dist/index.html')); }); // Register API routes first so they are not caught by the fallback.
10

How do you implement role-based access control (RBAC) in an API?

Save to ▾
Show answer
Define roles such as admin, manager and customer, and map them to permissions like order:read or order:refund. Put the role or permissions in the token or load them per request, and check them in middleware before handlers. For ownership rules, also check resource data, for example a customer can view only orders where order.userId equals req.user.id. Test both allowed and denied paths.
11

How would you design authentication for a system of ten microservices?

Save to ▾
Show answer
Centralise login in an identity service or provider such as Keycloak, Auth0 or Cognito that issues short-lived JWTs signed with RS256. The API gateway validates tokens, and each service verifies the signature using the public keys from a JWKS endpoint, so no shared secret is needed. Use service-to-service tokens or mTLS for internal calls and keep authorisation checks inside each service.
12

How do you use a message queue to process background jobs in Node.js?

Save to ▾
Show answer
const { Queue, Worker } = require('bullmq'); const connection = { host: 'redis', port: 6379 }; const emailQueue = new Queue('email', { connection }); await emailQueue.add('welcome', { userId }, { attempts: 5, backoff: { type: 'exponential', delay: 1000 }, jobId: `welcome:${userId}` }); new Worker('email', async (job) => { await sendWelcomeEmail(job.data.userId); }, { connection, concurrency: 10 });
13

How would you test code that depends on the current time, like an expiring coupon?

Save to ▾
Show answer
Inject a clock function instead of calling Date.now directly, or use Jest fake timers: jest.useFakeTimers().setSystemTime(new Date('2026-01-01')). Then test before, exactly at and after expiry. Store dates in UTC and convert for display in IST, which avoids bugs near midnight. Reset timers after each test with jest.useRealTimers to avoid leaking into other tests.
14

Two simultaneous requests both read a wallet balance, deduct money and save it, causing a wrong balance. How do you fix this race condition?

Save to ▾
Show answer
Async code interleaves between awaits, so read-modify-write is unsafe. Make the update atomic in the database: use an UPDATE with balance = balance - amount WHERE balance >= amount, or MongoDB $inc with a filter. Alternatives are row-level locks with SELECT FOR UPDATE inside a transaction, optimistic locking with a version column, or a Redis distributed lock for cross-service work.
15

What is the OWASP Top 10 and which items matter most for Node.js APIs?

Save to ▾
Show answer
The OWASP Top 10 lists the most critical web application security risks. For Node APIs the most relevant are broken access control, injection, cryptographic failures, security misconfiguration, vulnerable and outdated components, authentication failures and server-side request forgery. OWASP also publishes an API Security Top 10, which highlights broken object level authorisation, where users access others' data by changing an ID.
16

How do you load test a Node.js API before a big sale event?

Save to ▾
Show answer
Define targets from expected traffic, such as 5,000 requests per second with p95 under 300 ms. Write realistic scenarios in k6 or Artillery covering browse, cart and checkout, run them against a production-like environment, and ramp up gradually. Watch latency, error rates, CPU, memory, event loop lag and database metrics, then fix bottlenecks and rerun until targets are met with headroom.
17

Memory usage of a Node.js service grows steadily until the pod restarts. How would you find the leak?

Save to ▾
Show answer
First confirm with metrics that heap used keeps rising under steady traffic. Take heap snapshots with --inspect and Chrome DevTools or heapdump at intervals and compare them to find objects whose count keeps growing. Common causes are global caches without limits, event listeners added per request, closures holding large objects and unclosed timers. Fix, then load test with autocannon to verify heap stabilises.
18

How do you handle a breaking API change request from a product manager close to a release?

Save to ▾
Show answer
I would first understand why it is needed and who consumes the API. Then I explain the impact on existing clients, propose a non-breaking path such as adding a new field or a v2 endpoint, and estimate effort and risk. Result in a past case: we shipped the additive change on time and scheduled removal of the old field for the next quarter.
19

How do you enable compression and why should you be careful with it?

Save to ▾
Show answer
Use the compression middleware or, better, let Nginx or the CDN compress responses with gzip or Brotli, which reduces JSON payload size by 70 percent or more. Be careful: compressing in Node uses CPU on the event loop, small responses gain little, and already compressed files like images should be skipped. Never compress responses mixing secrets with user input over HTTPS because of BREACH-style attacks.
20

What are microtasks and macrotasks?

Save to ▾
Show answer
Macrotasks are scheduled work like setTimeout, setInterval, setImmediate and I/O callbacks, handled phase by phase by the event loop. Microtasks are promise reactions and queueMicrotask callbacks; they run right after the current synchronous code finishes and before the next macrotask. In Node, process.nextTick callbacks run even before promise microtasks. A long microtask chain can delay timers and I/O.
21

How do you prevent server-side request forgery when your API fetches a user-supplied URL?

Save to ▾
Show answer
An attacker could make your server call internal addresses such as 169.254.169.254 for cloud metadata or localhost admin ports. Allow only http and https, resolve the hostname and block private, loopback and link-local IP ranges, use an allowlist of domains where possible, disable redirects or revalidate them, set short timeouts and size limits, and run fetchers in an isolated network.
22

Where should a web app store tokens: localStorage or cookies?

Save to ▾
Show answer
localStorage is readable by any JavaScript on the page, so an XSS bug can steal tokens. HttpOnly, Secure, SameSite cookies cannot be read by JavaScript, which is safer for refresh tokens and session IDs. Cookies require CSRF protection, which SameSite=Lax or Strict plus CSRF tokens provide. A common pattern keeps the access token in memory and the refresh token in an HttpOnly cookie.
23

When would you use Kafka instead of a Redis-based queue like BullMQ?

Save to ▾
Show answer
BullMQ suits task queues inside one application: emails, reports, retries and scheduled jobs. Kafka is a distributed, durable event log for high-throughput streaming, where many consumer groups read the same events independently and can replay history, such as order events consumed by analytics, notifications and inventory. Kafka adds operational complexity, so use it when you need event streaming at scale.
24

How do you prevent a cache stampede when a popular key expires?

Save to ▾
Show answer
When a hot key expires, thousands of requests may hit the database at once. Solutions: allow only one request to rebuild the cache using a short Redis lock while others wait or serve stale data, refresh hot keys in the background before expiry, add random jitter to TTLs so keys do not expire together, and use stale-while-revalidate where slightly old data is acceptable.
25

How would you design an API for a long-running task such as exporting a 1 GB report?

Save to ▾
Show answer
Do not keep the HTTP request open. POST /exports creates a job, pushes it to a queue and returns 202 Accepted with a job ID and status URL. Clients poll GET /exports/:id or receive a webhook or WebSocket event. A worker generates the file, uploads it to object storage, and the status endpoint returns a short-lived signed download URL.
26

Describe a situation where you found and fixed a production performance problem.

Save to ▾
Show answer
Situation: our search API p95 latency jumped from 200 ms to 2 seconds after a release. Task: as on-call engineer I had to find the cause fast. Action: I checked APM traces, saw a new synchronous JSON transform blocking the event loop, moved it to a cached precomputed field and added an event loop lag alert. Result: latency returned to normal within a day and we added a performance check to code review.
27

A partner integration retries POST requests on timeouts and creates duplicate orders in your API. How would you redesign the endpoint?

Save to ▾
Show answer
Require an Idempotency-Key header on order creation and store it with a unique index alongside the created order ID and response. On a repeated key with the same payload, return the original response; with a different payload, return 409 or 422. Also add a unique business constraint such as partner order reference, respond quickly by queueing slow work, and document retry behaviour for partners.
28

Your JWT secret has leaked. What steps do you take?

Save to ▾
Show answer
Treat it as an incident. Generate a new secret and deploy it immediately, which invalidates all existing tokens and forces re-login. Revoke refresh tokens in the database, check logs for suspicious tokens or admin actions, and find how it leaked, for example a committed .env or logs. Move to a secrets manager, consider asymmetric RS256 keys with key IDs to rotate safely, and document the incident.
29

What is HATEOAS and is it used in real projects?

Save to ▾
Show answer
HATEOAS, Hypermedia as the Engine of Application State, means responses include links telling the client what it can do next, for example an order response with links to cancel or pay. It makes APIs more discoverable and decoupled. In practice most JSON APIs only partly use it, such as pagination links, because clients are usually built against documented endpoints.
30

Compare offset pagination and cursor pagination.

Save to ▾
Show answer
Offset pagination uses page and limit, translated to LIMIT and OFFSET. It is simple and allows jumping to a page, but gets slow on large tables and can skip or repeat rows when data changes. Cursor pagination uses the last seen value, such as id or created_at, to fetch the next set with a WHERE clause. It is fast and stable, ideal for feeds and infinite scroll.
31

Describe a time you led a technical decision that affected the whole team.

Save to ▾
Show answer
Situation: our five Node services used different logging and error formats, making incidents slow to debug. Task: as tech lead I wanted one standard. Action: I wrote a short RFC comparing options, built a shared package with pino, request IDs and an error handler, collected feedback and migrated one service as a pilot. Result: all services adopted it within a month and mean time to resolve incidents fell noticeably.
32

Should you use serverless functions like AWS Lambda for a Node.js API?

Save to ▾
Show answer
Serverless suits spiky or low-traffic workloads, event processing and quick prototypes, since you pay per invocation and need no server management. Downsides are cold starts, execution time limits, connection handling with relational databases and harder local debugging. For steady high traffic or long-lived WebSocket connections, containers are usually cheaper and simpler. Many teams mix both.
33

Write code to verify an HMAC signature on an incoming webhook in Express.

Save to ▾
Show answer
const crypto = require('crypto'); app.post('/webhooks/payment', express.raw({ type: 'application/json' }), (req, res) => { const sig = req.get('X-Signature') || ''; const expected = crypto .createHmac('sha256', process.env.WEBHOOK_SECRET) .update(req.body) .digest('hex'); const ok = sig.length === expected.length && crypto.timingSafeEqual(Buffer.from(sig), Buffer.from(expected)); if (!ok) return res.status(401).end(); handleEvent(JSON.parse(req.body)); res.status(200).end(); });
34

Tell me about a time a database change caused an issue and what you learned.

Save to ▾
Show answer
Situation: I added a NOT NULL column with a default to a large MySQL table during business hours. Task: the migration locked the table and checkout slowed down. Action: I rolled back, rewrote it as add nullable column, backfill in batches, then add the constraint, and ran it at low traffic after testing on a production-size copy. Result: no downtime, and we added a migration review checklist.
35

Implement cursor-based pagination for a products endpoint.

Save to ▾
Show answer
router.get('/products', async (req, res) => { const limit = Math.min(Number(req.query.limit) || 20, 100); const cursor = req.query.cursor; const filter = cursor ? { _id: { $lt: cursor } } : {}; const items = await Product.find(filter) .sort({ _id: -1 }) .limit(limit + 1); const hasMore = items.length > limit; if (hasMore) items.pop(); res.json({ data: items, nextCursor: hasMore ? items[items.length - 1]._id : null }); });
36

Your service calls three microservices and fails completely if one is down. How would you make it more resilient?

Save to ▾
Show answer
Use Promise.allSettled so one failure does not reject everything, and return partial data with clear flags. Add timeouts to every call, retries with backoff for transient errors and a circuit breaker such as opossum to stop hammering a failing service. Provide fallbacks like cached values and log failures with correlation IDs so the issue can be traced.
37

A Mongoose query returns large documents and the API is slow. What optimisations can you apply?

Save to ▾
Show answer
Use .select() to fetch only needed fields, and .lean() to return plain objects instead of full Mongoose documents, which cuts memory and CPU. Make sure the filter and sort use an index, checked with explain. Paginate results, avoid populating deep references, and cache frequently read data. For large exports, use a cursor with for await instead of loading everything.
38

A regex in your validation code makes the server hang on certain inputs. What is the issue?

Save to ▾
Show answer
This is likely ReDoS, regular expression denial of service. Patterns with nested quantifiers such as (a+)+ can backtrack exponentially on crafted input, blocking the event loop. Fix by simplifying the regex, limiting input length before matching, using well-tested validators like validator.js, or a linear-time engine such as re2. Add tests with long malicious strings.
39

Your Express API needs to support multiple client apps with different rate limits. How would you design it?

Save to ▾
Show answer
Identify the client through an API key or OAuth client ID in authentication middleware and attach the plan to req. Then use express-rate-limit or a custom limiter with a Redis store, keyed by client ID, with limits read from the plan. Return 429 with Retry-After and RateLimit headers. Redis keeps limits consistent across multiple server instances.
40

How do you manage database schema migrations in a Node.js project?

Save to ▾
Show answer
Use a migration tool such as Prisma Migrate, Knex, Sequelize CLI or TypeORM migrations, and commit migration files to Git. Each migration has up and ideally down steps and runs in CI and before deployment. For zero downtime, use expand and contract: add new columns first, deploy code that writes both, backfill, switch reads, then drop old columns in a later release.

Frequently asked questions

What is asked in Full Stack with Node.js interviews for 7 years of experience?

Seven-year candidates are evaluated as senior engineers or tech leads. Interviews include complex system design, cross-team technical decisions, migration strategies such as monolith to microservices, cost and reliability trade-offs and security architecture. Behavioural rounds test conflict handling, influencing without authority and delivery under pressure. Prepare clear stories with measurable impact on performance, reliability or developer productivity.

How many questions should I practise before a Full Stack with Node.js interview?

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

Which topics matter most for 7 years of experience?

Focus first on Architecture decisions, Migration strategy, Reliability and cost, Technical leadership.