Node.js Interview Questions: The Principal Architect Round

50 Highly Advanced, Production-tested Expert Node.js Interview Questions & Answers used by Technical Directors at Top MNCs.

Expert Level (Q1 – Q50)

Q01
How do V8 Hidden Classes and Inline Caches (ICs) impact Node.js object optimization?
Expert

V8 compiles JavaScript down to native machine code. Since JS is dynamically typed, V8 creates hidden internal classes (Shapes) under the hood to track property offsets. When an object changes its structure dynamically, V8 creates a new hidden class transition tree. Inline Caches store shortcuts for locating property locations within functions.

Real-Time Architectural Case: In a high-speed telemetry ingestion pipeline processing millions of coordinates, if you dynamically add fields to an object conditionally (e.g., `if(data.alert) obj.alert = true;`), you break hidden class consistency. This forces the function into a polymorphic or megamorphic state, dropping execution speed by over 60%. Always initialize objects with a rigid schema layout.
Q02
How do you precisely measure and alert on Event Loop Lag in a production environment?
Expert

Event Loop Lag cannot be calculated natively via traditional CPU usage percentages. You must measure the delay between when a timer was scheduled to execute versus when it actually runs. This can be accurately tracked using Node’s native `perf_hooks` module via the `monitorEventLoopDelay` function.

Real-Time Architectural Case: In a multi-billion dollar payment processing gateway, you monitor loop delay programmatically. If the lag exceeds 50 milliseconds, the system raises an immediate alert and configures the API Gateway to shed load (shedding low-priority read requests) before the system falls into a cascade failure due to timeout bottlenecks.
Q03
Why does `dns.lookup` cause severe performance bottlenecks under high concurrent outbound HTTP request volume, and how do you resolve it?
Expert

Node’s native `dns.lookup` is a synchronous, blocking system call that utilizes `getaddrinfo()` at the operating system level. Because it is synchronous, libuv is forced to execute it inside the internal thread pool, completely exhausting the default pool of 4 threads and stalling all other file system or crypto tasks.

Real-Time Architectural Case: A web-scraping worker cluster making thousands of outbound API calls per minute stalls out, causing timeouts. The architect resolves this by switching the implementation to use `dns.resolve()`, which operates entirely asynchronously via network sockets without consuming thread pool resources, combined with an internal HTTP Keep-Alive agent pool.
Q04
How do you engineer strict custom backpressure inside a custom Duplex or Transform stream?
Expert

Backpressure management inside custom streams requires monitoring the return value of `.write()`. If `.write(chunk)` returns `false`, the internal `highWaterMark` threshold has been breached. You must halt reading operations immediately and wait for the destination stream to emit the `’drain’` event before resuming transmission.

Real-Time Architectural Case: Designing an automated log-forwarding tool that transfers files from local systems to a remote storage endpoint. If the network interface degrades, the write buffer fills. By capturing the `false` threshold and executing `readableStream.pause()`, you prevent memory allocation creep that would otherwise trigger an Out-Of-Memory crash.
Q05
How do you implement a lock-free, zero-copy architecture between distinct Worker Threads using `SharedArrayBuffer` and `Atomics`?
Expert

To achieve maximum throughput without serialization overhead between workers, you use `SharedArrayBuffer`. It allocates memory outside the main V8 heap that can be shared across multiple threads directly. To avoid race conditions, you use the global `Atomics` object, which provides atomic thread-safe operations and wait/notify sync patterns.

Real-Time Architectural Case: In a high-frequency trading platform engine built with Node.js, Worker 1 writes raw price updates directly to a shared memory block, while Worker 2 reads and processes calculations. By utilizing `Atomics.wait()` and `Atomics.notify()`, the engine orchestrates synchronization at microsecond speeds without cloning data structures.
Q06
How do you configure programmatic, non-invasive memory heap dump captures when a server crosses critical thresholds in an automated environment?
Expert

You handle this by leveraging the native `v8` module’s `writeHeapSnapshot()` method inside an automated health monitor loop. You check the memory consumption using `process.memoryUsage().heapUsed` on a regular interval, and trigger a snapshot automatically if usage crosses a set limit.

Real-Time Architectural Case: An enterprise e-commerce backend experiences intermittent memory leaks only during seasonal traffic spikes. The architect writes a rule: If `heapUsed` goes above 85% of total allocated memory, execute `v8.writeHeapSnapshot(‘/mnt/dumps/’ + Date.now() + ‘.heapsnapshot’)`. This isolates the exact leaking objects right before the orchestration platform destroys the failing pod.
Q07
How do you accurately track down hot execution paths using V8 Sampling Profilers and Flame Graphs under sustained high load?
Expert

Under heavy production load, running a debugger causes unacceptable performance penalties. Instead, you boot the application with the `–prof` flag to collect V8 execution samples or run profiling tools like `0x` which utilize system trace mechanisms to capture execution stacks and generate a visual Flame Graph.

Real-Time Architectural Case: A real-time notification engine hits 100% CPU utilization unexpectedly. Running `0x` identifies a wide, deep mountain in the flame graph pinpointing a poorly optimized, highly complex Regular Expression checking user input strings inside an authentication middleware. Replacing the RegExp with index checks instantly recovers 70% CPU headroom.
Q08
What is the execution cost and internal mechanics of `AsyncLocalStorage` in enterprise APM tools?
Expert

`AsyncLocalStorage` relies on internal V8 hooks (`async_hooks`) to trace context continuity across execution contexts and event loops. Every asynchronous boundary crossing (e.g., an await statement) invokes a tracking hook, which incurs a small CPU runtime overhead depending on the nesting complexity.

Real-Time Architectural Case: Implementing end-to-end distributed tracing across microservices using OpenTelemetry. The `AsyncLocalStorage` safely binds the initial incoming HTTP Request ID across database queries, downstream outbound HTTP calls, and log statements, allowing engineering teams to correlate full execution trees in a centralized dashboard.
Q09
How can Prototype Pollution result in remote code execution (RCE) in a Node backend, and how do you structurally immunize a codebase against it?
Expert

Prototype Pollution occurs when user input modifies properties on `__proto__`. If an application uses an unvalidated deep-merge utility, an attacker can append global values. If the application later forks a child process using option configurations that fallback on defaults, the attacker can hijack execution arguments via polluted properties.

Real-Time Architectural Case: A user passes an injection payload into a profile management endpoint. To immunize the system against this vulnerability, the architect enforces the use of strict object schemas (`Object.create(null)` for map dictionaries), validates all incoming payloads with a rigid validation layer like Zod, and seals critical prototypes globally using `Object.freeze(Object.prototype)`.
Q10
How do you handle edge-case race conditions and clock-drift when deploying the Redlock algorithm over Redis clusters in Node.js?
Expert

The Redlock algorithm requires acquiring locks across multiple independent Redis instances concurrently using matching random string validations. To handle clock drift between physical servers, the lock validity time must be adjusted downwards by subtracting a drift factor (a few milliseconds) to guarantee safe mutual exclusion.

Real-Time Architectural Case: During a high-demand flash sale ticketing event, multi-pod Node.js servers attempt to allocate a limited set of premium seats. By wrapping the operation inside `ioredis` utilizing the `redlock` algorithm with a tight 500ms timeout limit, the backend eliminates ticket double-allocation issues completely without bottlenecking single-node performance.
Q11
How do you implement the Saga Pattern to orchestrate multi-microservice transactions with guaranteed eventual consistency and automated rollbacks?
Expert

Since microservices manage isolated databases, traditional ACID transactions across them are impossible. The Saga pattern designs a workflow as a series of distinct local transactions. Each step has a corresponding reverse “compensating transaction” that executes if any subsequent phase fails, ensuring data consistency.

Real-Time Architectural Case: A travel booking flow. Node microservice 1 reserves a flight, service 2 charges a credit card, and service 3 reserves a hotel. If service 3 fails due to room availability, the orchestrator triggers compensating endpoints: service 2 refunds the card charge, and service 1 frees the flight seat reservation automatically.
Q12
How do you explicitly tune an enterprise outbound HTTPS Agent to manage thousands of cross-service connections through AWS ALBs without encountering random socket drop errors?
Expert

By default, Node’s global HTTP Agent does not enforce tight configuration constraints under massive production loads. You must instantiate a custom `https.Agent` specifying parameters like `keepAlive: true`, `maxSockets: Infinity`, `maxFreeSockets: 256`, and align the `keepAliveMsecs` parameter to exactly match or fall below the timeout configuration of your downstream load balancer.

Real-Time Architectural Case: A Node.js backend cluster frequently drops connections with ECONNRESET errors when calling downstream internal microservices. The architect discovers the AWS Application Load Balancer has an idle timeout of 60 seconds, while Node’s default agent timeout is shorter. Aligning the connection configurations eliminates the socket drops.
Q13
How can heavy cryptographic processing cause Event Loop starvation in a high-throughput authentication route, and how do you resolve it?
Expert

Executing synchronous hashing methods (such as `crypto.pbkdf2Sync` or `bcrypt.hashSync`) directly inside a request thread forces the event loop to stop processing everything else for the duration of the calculation. This blocks all other incoming requests from being read or responded to.

Real-Time Architectural Case: During morning login surges on an enterprise HR platform, general user response times spike to 15 seconds. The engineer replaces the blocking code with the asynchronous `crypto.pbkdf2()` implementation or routes the hashing jobs into a dedicated thread pool via Piscina, restoring standard API response times across the board.
Q14
How do you build a resilient Circuit Breaker mechanism with graceful degradation when dealing with flaky downstream legacy SOAP/REST dependencies?
Expert

A circuit breaker pattern tracks call failures using three operational states: **Closed** (normal traffic), **Open** (failing fast without hitting the degraded dependency), and **Half-Open** (allowing a slow trickle of testing requests to pass through). You implement this pattern using libraries like `opossum` wrapped around outward-facing request closures.

Real-Time Architectural Case: An internal e-commerce service pulls shipping rates from a legacy external enterprise system. If that external provider experiences latency, your system fails fast by returning a cached fallback shipping flat-rate immediately instead of exhausting connections waiting on timeouts.
Q15
What are the performance limits of the native `JSON.stringify` under large payloads, and what alternative optimization strategies exist for high-volume logs?
Expert

The native `JSON.stringify` operation executes completely synchronously. If an API attempts to serialize a massive 50MB nested relational data object, the main loop locks up entirely while traversing the data structure. You optimize this by using schema-based serialization compilers like `fast-json-stringify`.

Real-Time Architectural Case: A logging microservice handles heavy metrics collection. By switching from standard serialization to `fast-json-stringify` with predefined structural JSON schemas, the team achieves a 2x throughput boost because the serialization code is pre-compiled for that exact object structure.
Q16
How do you prevent a Cache Stampede (Thundering Herd) crash on core database infrastructure when high-frequency cache keys expire simultaneously?
Expert

To mitigate cache stampede, you use an Asynchronous Request Coalescing layer (often called a Single-Flight pattern). When a cache miss happens, instead of letting all 500 concurrent requests query the database at once, you intercept them and ensure only the first request queries the DB while the other 499 hook into its returned Promise.

Real-Time Architectural Case: The homepage configuration cache for a media application expires. The backend leverages an internal data-coalescing map. This routes a single query to the primary database instance while resolving all matching user connections smoothly the millisecond the data is fetched.
Q17
How do you fine-tune the `highWaterMark` buffer sizing when building high-throughput file ingestion streaming pipelines to cloud buckets?
Expert

The default `highWaterMark` for readable streams is 16KB (and 64KB for writable streams). When streaming massive enterprise files, small buffer thresholds generate thousands of tiny chunk operations, causing high CPU overhead. Bumping this property to larger boundaries (e.g., 1MB or 4MB) optimizes the underlying system reads.

Real-Time Architectural Case: An application processes multi-gigabyte raw video uploads, transferring them directly to an AWS S3 bucket. Tuning the chunk size constraints to 4MB allows the application to maximize network bandwidth and match the memory multi-part upload limits required by the cloud API.
Q18
How do you securely implement API credential comparisons to protect against low-level remote timing attacks?
Expert

Standard string comparison operators (`===`) break evaluation early the exact millisecond a character mismatch is detected. An attacker can map out the character length of a secret key by measuring tiny nanosecond variations in response times. To solve this, you use fixed-time comparison functions.

Real-Time Architectural Case: A webhook verification route inspects signature tokens. By routing the signature checks through `crypto.timingSafeEqual(Buffer.from(signature), Buffer.from(expected))`, the execution time remains identical regardless of where a character mismatch occurs, neutralising timing vector attacks.
Q19
How do you horizontally scale stateful WebSockets architectures across multiple cloud instances without dropping active room communication frames?
Expert

Since WebSockets keep an open TCP connection to a specific server instance, Server 1 cannot natively communicate with a client connected to Server 2. You solve this horizontal scale limitation by putting an asynchronous message distribution layer (like Redis Pub/Sub) behind your WebSocket nodes.

Real-Time Architectural Case: A real-time collaborative whiteboarding system. By connecting the `socket.io` architecture to an external clustered Redis adapter, any update event emitted by a user on Node Server A is instantly published to Redis, which forwards the frame to all other server nodes for broadcast.
Q20
When and how should you implement native C++ Addons via Node-API (N-API) instead of standard JavaScript loops?
Expert

You use Native C++ Addons when you need to perform heavy CPU-bound computing (like machine learning models, custom compression algorithms, or image manipulation) that exceeds the performance of the V8 JavaScript interpreter. Node-API provides binary stability across distinct Node versions.

Real-Time Architectural Case: An asset management service needs to extract complex metadata from raw medical images on the fly. Writing the parsing logic in JavaScript causes high CPU lag. The team wraps a high-performance native C++ parsing engine using Node-API, achieving a 10x processing speedup.
Q21
How do you structure low-overhead, in-memory caching layers using raw JavaScript `TypedArrays` to bypass V8 Garbage Collection overhead?
Expert

V8 tracks standard JavaScript objects inside its heap layout, which requires regular garbage collection (GC) sweeps. If you store millions of objects in an in-memory cache, the GC pauses will grow longer and degrade performance. `TypedArrays` (like `Int32Array` or `Float64Array`) allocate raw un-managed binary buffers, bypassing V8 GC sweeps entirely.

Real-Time Architectural Case: A routing service maps millions of tracking coordinates in real-time. Instead of caching them as standard JS objects, the architect packs the data points directly into a single large `ArrayBuffer`. This keeps heap-object counts low and keeps GC pause times under 2ms even under heavy load.
Q22
How do you mitigate database replication lag anomalies inside high-throughput Node.js microservices?
Expert

Replication lag happens when data written to a primary database has not yet synced to a read replica. If a Node service writes a record and then immediately tries to read it from a replica, it will encounter a 404 Not Found anomaly. You solve this by implementing data-routing logic.

Real-Time Architectural Case: A user updates their profile picture and immediately refreshes the page. The architect implements an intentional routing rule: Any write action flags that specific user’s session ID in Redis for 5 seconds, forcing all subsequent read requests within that window to hit the primary database directly.
Q23
How do you re-architect Express routing mechanisms to eliminate linear O(N) lookup latency when dealing with thousands of dynamic endpoint configurations?
Expert

Express evaluates routes linearly in the order they are defined. If an application grows to have thousands of routes, matching a request at the bottom of the list requires checking every previous route structure, which incurs an $O(N)$ lookup penalty. You solve this by implementing Radix-Trie based routers like `find-my-way` or switching to Fastify.

Real-Time Architectural Case: A multi-tenant enterprise CMS generates custom URLs for thousands of customer landing pages. Switching the underlying routing mechanism from Express to a Radix-Trie architecture drops base route matching time from 15ms down to nanoseconds, independent of the total number of routes.
Q24
How do you leverage ECMAScript Modules (ESM) dynamic imports to build safe, hot-swappable multi-tenant runtime extension architectures?
Expert

Dynamic `import()` expressions allow you to load modules asynchronously at runtime based on variables. This enables you to load isolated tenant code blocks on demand, rather than pre-loading every custom module into memory at server startup.

Real-Time Architectural Case: An enterprise payment processing application handles dynamic integrations for various vendors. When a transaction arrives, Node executes `const plugin = await import(`./plugins/${tenantId}.js`)`. This pattern allows the system to support new vendor configurations instantly without requiring a server reboot.
Q25
How do you configure a raw Node.js HTTP server to defend against advanced Slowloris Denial of Service (DoS) attacks?
Expert

Slowloris attacks consume server connection limits by opening sockets and sending tiny fragments of HTTP header data very slowly, keeping the connections open as long as possible. You defend against this by tuning the underlying server timeout limits, such as `requestTimeout`, `headersTimeout`, and `keepAliveTimeout` on the HTTP server instance.

Real-Time Architectural Case: An edge Node.js service is targeted by a Slowloris attack that threatens to exhaust its connection pool. The engineer sets `server.headersTimeout = 5000` and `server.requestTimeout = 10000`. This causes the server to automatically drop connections that take too long to transmit their initial headers, neutralizing the attack.
Q26
How do you fine-tune the V8 Garbage Collector flags inside long-running data processing microservices to avoid catastrophic “Stop-The-World” pauses?
Expert

When the V8 heap grows large, major garbage collection sweeps can cause “Stop-The-World” pauses that freeze execution for several seconds. You can mitigate this by tuning runtime options via your command configuration, using flags like `–max-old-space-size`, `–optimize-for-size`, and adjusting the incremental marking steps.

Real-Time Architectural Case: A background data processing service regularly crashes or hits latency spikes when running large batch imports. The architect sets `–max-old-space-size=4096` and `–max-semi-space-size=128`. This gives the garbage collector more breathing room and reduces overall pause durations.
Q27
How do you stream millions of records from a database query directly down an HTTP response without buffering data in memory?
Expert

Loading millions of database rows directly into a standard array will quickly exhaust your server’s RAM and cause an out-of-memory crash. Instead, you should fetch the data using database streaming cursors and pipe those chunks directly into the HTTP response object.

Real-Time Architectural Case: An internal administration panel allows users to export 10 million rows of accounting transactions to a CSV file. The engineer leverages a PostgreSQL cursor stream via `pg-query-stream`, transforming the rows to CSV format on the fly and piping them directly into `res`. This processes the export efficiently using less than 50MB of memory.
Q28
How do you design an absolute idempotent request processing layer using Redis for message-driven billing architectures?
Expert

To guarantee idempotency, every incoming transaction must pass a unique `Idempotency-Key`. Before executing any business logic, Node checks for the existence of this key in Redis using an atomic operation like `SETNX`. If the key already exists, the system bypasses execution and returns the original cached response.

Real-Time Architectural Case: A subscription billing webhook receives occasional duplicate events due to network retries. By executing a Redis transaction that locks the `Idempotency-Key` with a 24-hour expiration window, you ensure users are never mistakenly charged twice for the same event.
Q29
How do you programmatically detect memory leaks in a production environment using the V8 Sampling Heap Profiler?
Expert

You can identify memory trends programmatically by leveraging the native `v8` module’s heap profiling tools. By taking regular samples of heap allocations over time, you can flag specific object structures that are growing continuously without being cleaned up by the garbage collector.

Real-Time Architectural Case: A long-running real-time data worker shows a slow memory creep over several days. The team configures the app to stream allocations using `v8.getHeapSnapshot()`. This reveals that a third-party event library is continuously retaining references to disconnected client objects.
Q30
How do you implement a CQRS pattern in a Node.js microservice architecture with optimized read/write performance?
Expert

Command Query Responsibility Segregation (CQRS) separates data modification operations (Commands) from data read operations (Queries). In Node, you can optimize this by using separate database models or entirely separate services for handling writes versus reads.

Real-Time Architectural Case: A high-traffic ride-hailing API handles continuous coordinate updates (writes) alongside user searches for nearby drivers (reads). The system routes writes through a high-throughput write pipeline backed by Kafka and PostgreSQL, while reads are served instantly from a replicated Elasticsearch cluster.
Q31
How do you handle safe, file-system level mutual exclusion across multiple independent forked Node.js processes?
Expert

Because distinct operating system processes cannot share standard in-memory locks, you must implement mutual exclusion at the OS kernel level. This can be achieved by using file descriptor locks via system calls like `flock` or using the `fs-ext` library’s lock functionality.

Real-Time Architectural Case: A clustered application writes server metrics to a shared local database file. To prevent data corruption from concurrent writes, each worker must successfully run `fsExt.flock(fd, ‘ex’)` to acquire an exclusive lock on the file before writing, ensuring data integrity.
Q32
How do you configure Mutual TLS (mTLS) for secure, authenticated communication between internal Node.js microservices?
Expert

Mutual TLS requires both the client and the server to validate each other’s X.509 certificates before establishing a connection. In Node, you configure this inside the `https` or `tls` module options by setting `requestCert: true` and `rejectUnauthorized: true`, along with your trusted Certificate Authority (CA) files.

Real-Time Architectural Case: A sensitive core banking microservice communicates with a transaction processor. By enforcing mTLS across their internal connections, you ensure that even if an attacker breaches the internal network, they cannot spoof requests to the core banking service without a valid certificate.
Q33
How do you implement client throttling during stream processing when down-stream network bottlenecks occur?
Expert

When streaming data to a client over a slow network connection, the server’s writable stream buffer will fill up, causing backpressure. You handle this by listening for the `.write()` method’s `false` return value, pausing the upstream data source, and resuming it only when the socket fires the `’drain’` event.

Real-Time Architectural Case: A file server streams large data exports to a mobile app over a weak cellular network. By tracking backpressure signals on the response object, Node pauses reading from the database when the network is congested, preventing the server’s RAM from filling with un-transmitted data.
Q34
What is a Reentrancy Attack in asynchronous middleware chains, and how do you protect your code against it?
Expert

A reentrancy issue occurs when an asynchronous function is called again before its first invocation has completely finished processing, which can lead to race conditions or unexpected state modifications if the function relies on shared variables.

Real-Time Architectural Case: An inventory management route checks stock levels, waits for an asynchronous database call, and then decrements the count. If a user double-clicks rapidly, two requests might pass the stock check before either updates the database. You prevent this by using mutex locks or atomic database adjustments like `SET stock = stock – 1`.
Q35
How do you optimize serverless Node.js AWS Lambda execution using V8 Code Caching techniques?
Expert

Serverless functions often suffer from cold start delays while the runtime initializes and compiles code. You can optimize this by utilizing V8 code caching, which stores the compiled machine code of your modules so subsequent invocations can skip the compilation step entirely.

Real-Time Architectural Case: A critical API endpoint runs on AWS Lambda. The team leverages bundlers like esbuild along with features like AWS Lambda’s provisioned concurrency or custom V8 snapshot tools. This reduces cold start initialization times from 800ms down to single-digit milliseconds.
Q36
How do you securely execute untrusted, user-submitted JavaScript code inside a multi-tenant Node.js application?
Expert

Using the native `vm` module to run untrusted code is unsafe because a malicious script can break out of the context and access the main process. For true isolation, you must execute untrusted code using advanced sandboxing libraries like `isolated-vm`, which runs code within isolated V8 Isolate instances.

Real-Time Architectural Case: An automation platform allows users to write custom JavaScript snippets to transform webhook data. By executing these snippets inside an `isolated-vm` container with strict memory limits (e.g., 128MB) and a tight execution timeout (e.g., 200ms), you prevent infinite loops or malicious scripts from crashing your server.
Q37
How do you synchronize real-time application state across multiple geographically separated cloud data centers?
Expert

Synchronizing data across regions requires an architecture that can handle network latency and potential network partitions. You can coordinate this by using globally distributed databases like Amazon Aurora Global Database or setting up multi-region message replication using systems like Apache Kafka.

Real-Time Architectural Case: A collaborative document editing tool runs nodes in both the US and Europe. When a change happens, the local region processes the update instantly over WebSockets for low latency, while streaming the state change asynchronously to a global Kafka cluster to sync the other region.
Q38
How do you differentiate between Operational Errors and Programmer Errors in production, and how should your handling strategy change?
Expert

Operational errors are predictable runtime failures (such as a database timeout or a invalid user input) that must be caught and handled gracefully. Programmer errors are bugs in the code (such as a `TypeError` or an undefined reference) that put the application into an unstable, unpredictable state.

Real-Time Architectural Case: When an operational error occurs (e.g., a 3rd party API fails), your system logs it and returns a clean error message to the user. If a programmer error occurs (e.g., a null pointer), the app logs the stack trace to Sentry and intentionally calls `process.exit(1)`, allowing PM2 or Kubernetes to restart the container cleanly.
Q39
How and when should you force manual Garbage Collection in high-volume batch data operations?
Expert

Forcing garbage collection manually is generally discouraged because it interrupts execution flow. However, in heavy batch processing scripts that load and discard millions of data rows, you can run Node with the `–expose-gc` flag and call the global `gc()` function after processing each batch to free up memory immediately.

Real-Time Architectural Case: A nightly data migration task processes blocks of 500,000 records from an old database. To keep memory usage flat and prevent the script from running out of RAM, the developer adds an explicit `global.gc()` call at the end of each block’s execution loop.
Q40
How do you implement OpenTelemetry Context Propagation across distributed asynchronous microservice boundaries?
Expert

Distributed tracing requires passing tracing headers (like `traceparent`) across network requests. OpenTelemetry uses Context Propagation to inject these trace IDs into outgoing HTTP request headers or message broker properties, allowing downstream services to continue the same trace context.

Real-Time Architectural Case: A request enters an API Gateway. OpenTelemetry initializes a trace context. When the gateway calls an internal billing service via HTTP, OpenTelemetry injects the trace header. The billing service reads this header, ensuring all logs across both services are tied to the same original user request.
Q41
How can a memory leak occur within JavaScript closures, and how do you trace it back to the source code?
Expert

A closure leak happens when a long-lived function or object retains a reference to a parent scope variable that is no longer needed. If that variable holds a large object (like a request context), that memory cannot be cleaned up by the garbage collector as long as the closure remains active.

Real-Time Architectural Case: An authentication middleware sets a timeout handler that references the main request object. If the timeout is never cleared properly via `clearTimeout()`, the request object remains locked in memory. You find this by analyzing a Heap Snapshot and finding unexpected instances of `IncomingMessage` tied to timer handles.
Q42
How do you manage high-throughput CPU tasks using a dynamically scaling pool of Worker Threads with Piscina?
Expert

Manually creating worker threads for individual tasks creates significant performance overhead. Instead, you should use a dedicated thread pool manager like `piscina`. It maintains a stable pool of reusable workers, queueing up incoming tasks and distributing them efficiently across available CPU cores.

Real-Time Architectural Case: A media management API handles heavy batch image conversions. Instead of running these calculations on the main thread, the app forwards the image buffers to a `piscina` worker pool, utilizing all available CPU cores without blocking incoming API traffic.
Q43
What are the performance differences between HTTP/2 multiplexing and HTTP/1.1 connection limits in microservice networks?
Expert

HTTP/1.1 limits browsers or client agents to a small number of concurrent TCP connections (typically 6) per domain, meaning requests can get queued behind slow operations. HTTP/2 uses multiplexing to send multiple requests and responses concurrently over a single TCP connection, reducing connection overhead.

Real-Time Architectural Case: An internal dashboard application fetches hundreds of small data points from various microservices. Switching the internal network communication from HTTP/1.1 to HTTP/2 multiplexing removes connection queuing delays and reduces server resource usage by eliminating duplicate TCP handshakes.
Q44
How do you implement a Two-Phase Commit (2PC) protocol for distributed database operations across heterogeneous systems?
Expert

A Two-Phase Commit ensures atomic updates across multiple distinct database instances. It operates in two steps: 1) The coordinator service asks all participating databases to **Prepare** and lock the necessary records, and 2) If all databases report success, the coordinator issues a global **Commit** command; otherwise, it aborts the operation.

Real-Time Architectural Case: A financial application updates a ledger in a PostgreSQL database while simultaneously syncing the transaction state to a legacy mainframe system. The coordinator service orchestrates a two-phase check to ensure both systems update successfully or roll back completely on error.
Q45
How do you engineer a Sliding Window Log rate-limiting algorithm using Redis pipeline evaluations?
Expert

A sliding window rate limiter tracks timestamps for every request inside a Redis sorted set (`ZSET`). For each incoming request, the application runs a Redis pipeline that removes timestamps older than the current window, counts the remaining elements in the set, and adds the new timestamp if the limit hasn’t been breached.

Real-Time Architectural Case: A public open data API protects itself against aggressive scraping bots. By executing a Redis sorted set pipeline for each API key, the system enforces a strict limit (e.g., maximum 100 requests per rolling 60-second window), blocking spikes cleanly without heavy database overhead.
Q46
How do you implement atomic counter updates in Redis using Lua scripts to prevent race conditions during high-concurrency ticket sales?
Expert

Standard Redis commands like `GET` and `SET` run sequentially, but if multiple distinct Node processes execute them concurrently, you can still experience race conditions. You can solve this by writing your evaluation logic inside a Lua script. Redis executes Lua scripts atomically, ensuring no other commands can run mid-execution.

Real-Time Architectural Case: A concert ticketing platform launches a highly popular ticket sale. The application runs a Lua script inside Redis that reads the remaining ticket count, verifies there is stock available, and decrements the counter in one single atomic operation, preventing ticket overselling.
Q47
How do you manage shared code modules and optimize deployment artifacts inside large-scale monorepos using workspaces?
Expert

Monorepos use package manager workspaces (like npm, yarn, or pnpm workspaces) to manage multiple independent applications alongside shared utility libraries in a single repository. This allows projects to reference local packages directly without publishing them to an external registry.

Real-Time Architectural Case: An enterprise monorepo contains 10 distinct microservices along with a shared database schema module. When building a production Docker image for a single microservice, you use workspace filtering commands to only package that specific app and its direct local dependencies, keeping deployment images clean and lightweight.
Q48
How do you update application configuration settings at runtime across a multi-node cluster without restarting the processes?
Expert

Instead of restarting servers to pick up configuration changes, your Node.js application can listen for live configuration updates using a centralized system or a message broker channel like Redis Pub/Sub.

Real-Time Architectural Case: A technical director needs to enable a high-verbosity logging mode to debug a production issue. They publish a configuration message to a Redis Pub/Sub channel. All 50 active Node server nodes listen for this event and dynamically update their internal logger configurations on the fly without dropping a single active connection.
Q49
How do you diagnose and triage unmanaged memory leaks that occur inside third-party native C++ addons?
Expert

Standard V8 heap snapshots only show memory managed by the JavaScript engine; they will not show leaks that occur in raw C++ code. To track down unmanaged memory leaks inside native addons, you must profile the entire Node process using system-level tools like Valgrind, leaks, or TCMalloc.

Real-Time Architectural Case: A video streaming API uses a native C++ wrapper module for video compression, and the server process regularly runs out of RAM. Since V8 snapshots look clean, the architect runs the app inside Valgrind, which pinpoints a missing `free()` call inside the native C++ code’s frame allocation loop.
Q50
How do you properly intercept and recover from stream errors across multi-stage piped node pipelines to prevent application crashes?
Expert

Using standard `.pipe()` chaining does not forward errors downstream. If an error occurs in the first stream of a chain, it will go unhandled and crash the application. To handle errors safely across a multi-stage pipeline, you should use the native `stream.pipeline()` function, which catches errors at any stage and handles cleanup automatically.

Real-Time Architectural Case: A data processing pipeline reads compressed log files, unzips them, parses the text content, and writes the results to a database. By wrapping the flow inside `pipeline(readStream, gunzipStream, parserStream, dbWriteStream, (err) => { … })`, any file corruption error is caught safely, closing all involved streams immediately to prevent memory leaks.

Node.js Interview Questions: The Core Developer Round

50 Intermediate Practical Node.js Questions asked in Top MNCs focusing on Architecture, Performance, and Microservices.

Intermediate Level (Q1 – Q50)

Q01
What is the specific role of `libuv` in Node.js architecture?
Intermediate

`libuv` is a multi-platform C library that provides support for asynchronous I/O based on event loops. It abstracts non-blocking I/O operations (file system, networking) to provide a consistent interface across different operating systems, and it manages the internal thread pool.

Real-World Example: When you call `fs.readFile()`, V8 delegates this to `libuv`. `libuv` talks to the OS using epoll (Linux) or IOCP (Windows) to read the file in the background, waking up the main JavaScript thread only when the data is ready.
Q02
Explain the phases of the Node.js Event Loop.
Intermediate

The Event Loop runs in a specific order of phases: 1) Timers (`setTimeout`, `setInterval`), 2) Pending Callbacks (I/O callbacks deferred to the next iteration), 3) Idle/Prepare (internal use), 4) Poll (retrieve new I/O events), 5) Check (`setImmediate`), and 6) Close Callbacks (e.g., `socket.on(‘close’)`).

Problem Scenario: If you put a heavy synchronous script inside a `setTimeout`, it blocks the Timers phase. Consequently, the Poll phase is delayed, meaning your server temporarily stops accepting incoming network requests.
Q03
How and why would you alter the `UV_THREADPOOL_SIZE`?
Intermediate

By default, `libuv` creates a thread pool of 4 threads to handle heavy tasks like DNS lookups, crypto operations, and file I/O. You can alter it by setting `process.env.UV_THREADPOOL_SIZE = ‘x’` (up to 1024) before your app boots.

Real-World Example: If your Node server handles heavy `bcrypt` hashing on user login, and 5 users log in simultaneously, the 5th user must wait because the default 4 threads are occupied. Bumping the pool size to 8 (if your CPU has the cores) drastically reduces the 5th user’s latency.
Q04
What is backpressure in Node.js streams?
Intermediate

Backpressure occurs when data is being read from a source faster than it can be written to a destination. The writable stream’s internal buffer fills up, and it must signal the readable stream to pause until the buffer drains to prevent memory exhaustion.

Problem Scenario: You are downloading a 5GB file (fast readable stream) and writing it to a slow hard drive (slow writable stream). Without handling backpressure, Node will cache the excess data in RAM, eventually crashing the server with an Out of Memory (OOM) error.
Q05
How does `.pipe()` differ from the new `pipeline()` method?
Intermediate

`.pipe()` automatically manages backpressure, but it does not automatically destroy connected streams if an error occurs in the middle of the chain, leading to memory leaks. `pipeline()` (from the `stream` module) safely handles errors and properly cleans up all streams involved.

Real-World Example: When piping a user upload to AWS S3, always use `pipeline(req, s3Stream, (err) => {…})`. If the user disconnects their WiFi mid-upload, `pipeline` destroys the S3 stream immediately, whereas `.pipe()` would leave it hanging.
Q06
How do you gracefully shutdown a Node.js server?
Intermediate

A graceful shutdown involves listening to OS signals (`SIGINT`, `SIGTERM`), stopping the server from accepting new connections (`server.close()`), completing existing active requests, closing database connections, and finally calling `process.exit(0)`.

Real-World Example: In Kubernetes, pods are frequently destroyed during scaling. If you don’t catch `SIGTERM` and shutdown gracefully, users in the middle of a checkout process will receive aggressive connection reset errors instead of completing their transaction.
Q07
What is the difference between `cluster` and `worker_threads`?
Intermediate

The `cluster` module forks the entire Node.js process. Each fork has its own V8 instance, memory, and Event Loop, but shares server ports (great for horizontal scaling). `worker_threads` share the same process memory (via ArrayBuffers) and are designed to offload CPU-heavy mathematical tasks within a single app instance.

Real-World Example: Use `cluster` (or PM2) to scale your Express API across an 8-core CPU to handle more HTTP traffic. Use `worker_threads` inside a specific route to generate a complex PDF report without blocking the rest of the API.
Q08
How do you debug memory leaks in Node.js?
Intermediate

You start the Node process with the `–inspect` flag and connect Chrome DevTools. You take a Heap Snapshot, run a load test against your API, and take another snapshot. By comparing the two (Heap Allocation Timeline), you can identify objects (like closures or arrays) that are not being garbage collected.

Problem Scenario: Your server restarts every 3 days. By taking heap snapshots, you discover a Winston logger configuration is inadvertently storing every incoming HTTP request object in a global array instead of writing them to a file.
Q09
Why is `process.nextTick()` dangerous if misused?
Intermediate

Callbacks registered with `process.nextTick()` are executed immediately after the current operation, before the Event Loop continues. If you recursively call `nextTick()`, you can cause “I/O Starvation,” where the Event Loop is locked and never reaches the Poll phase to handle incoming requests.

Real-World Example: Using a recursive `process.nextTick()` to process a massive array of 1,000,000 items will completely freeze the server for all other users. For heavy iterations, use `setImmediate()` to allow I/O to be processed in between chunks.
Q10
Explain the concept of “Event Emitter Memory Leaks.”
Intermediate

If you repeatedly attach listeners to an EventEmitter (e.g., inside a middleware or request handler) without removing them via `emitter.removeListener()`, the emitter retains a reference to the callback closures, preventing them from being garbage collected.

Problem Scenario: Doing `process.on(‘message’, handler)` inside a user request route means every time a user hits that route, a new listener is added. Node will eventually warn you: MaxListenersExceededWarning: Possible EventEmitter memory leak detected.
Q11
How does JWT differ from Session Cookies?
Intermediate

Session cookies are stateful; the server stores a Session ID in memory/Redis and sends a cookie to the client. The server must check the DB on every request. JWT is stateless; the payload (e.g., user role) is cryptographically signed and stored on the client. The server mathematically verifies the signature without querying the database.

Real-World Example: For microservices, JWTs are vastly superior. An Auth service generates the JWT, and a completely separate Billing service can verify the user’s identity independently without needing to connect to the Auth database.
Q12
What are the security vulnerabilities of storing JWTs in LocalStorage?
Intermediate

Storing JWTs in LocalStorage makes them vulnerable to Cross-Site Scripting (XSS). If an attacker injects malicious JavaScript into your site, that script can easily read `localStorage.getItem(‘token’)` and steal the user’s identity.

Problem Scenario: The most secure way to store tokens in a web app is to have the Node backend send the JWT as an `HttpOnly`, `Secure` cookie. JavaScript cannot read `HttpOnly` cookies, completely mitigating token theft via XSS.
Q13
What is CSRF and how do you protect a Node API against it?
Intermediate

Cross-Site Request Forgery (CSRF) is when a malicious site tricks a user’s browser into making an authenticated request to your site (using their active cookies). You protect against it by implementing Anti-CSRF tokens (using packages like `csurf`) or setting the `SameSite` attribute on your cookies.

Real-World Example: A user logs into their bank. In another tab, they click a malicious link that submits a hidden POST request to `bank.com/transfer`. Because `SameSite=Strict` is configured in your Express cookie settings, the browser blocks the cookie from being sent via the malicious site.
Q14
How do you implement Rate Limiting in Express?
Intermediate

Rate limiting restricts the number of requests a client (usually identified by IP address) can make in a given timeframe. It is typically implemented using middleware like `express-rate-limit` backed by an in-memory store or Redis for distributed systems.

Real-World Example: To prevent brute-force credential stuffing on your `/login` route, you apply a strict rate limit: maximum 5 requests per 15 minutes per IP. Any further requests automatically return an HTTP 429 (Too Many Requests).
Q15
Why use Redis with a Node.js application?
Intermediate

Redis is an in-memory key-value data store. Because Node is single-threaded, querying a traditional DB (like Postgres) for frequently accessed, unchanging data is slow. Redis acts as a caching layer, returning data in sub-milliseconds.

Real-World Example: An e-commerce API fetching a list of product categories. Since categories rarely change, you query Postgres once, store the JSON string in Redis, and serve all subsequent requests directly from Redis, dropping response times from 100ms to 2ms.
Q16
Explain Connection Pooling.
Intermediate

Opening a new database connection for every HTTP request is incredibly resource-intensive (TCP handshakes, authentication). A connection pool creates a set number of DB connections on startup and reuses them across requests.

Problem Scenario: Using `pg` (PostgreSQL client) without a pool in a high-traffic app will rapidly hit the database’s max connection limit, causing the API to crash. Using `new Pool({ max: 20 })` ensures requests wait in line for an available connection rather than crashing the DB.
Q17
How do you handle uncaught exceptions and unhandled promise rejections safely?
Intermediate

You listen to `process.on(‘uncaughtException’)` and `process.on(‘unhandledRejection’)`. However, it is dangerous to keep the server running after an uncaught exception due to unpredictable state. You should log the error to a service (like Sentry), and then synchronously shut down the process (`process.exit(1)`), letting a process manager (PM2/Kubernetes) restart it cleanly.

Problem Scenario: Ignoring unhandled rejections used to just print a warning, but in modern Node.js versions (v15+), an unhandled Promise rejection automatically crashes the entire application by default.
Q18
What is the purpose of the `crypto` module?
Intermediate

The built-in `crypto` module provides cryptographic functionality that includes a set of wrappers for OpenSSL’s hash, HMAC, cipher, decipher, sign, and verify functions.

Real-World Example: When integrating Stripe webhooks, you receive an HTTP request claiming to be from Stripe. You use `crypto.createHmac()` with your Stripe Secret to hash the payload. If your hash matches the header signature, you process the payment; otherwise, it’s an attacker.
Q19
Explain the concept of Middleware Error Handling in Express.
Intermediate

In Express, an error-handling middleware is distinct because it takes exactly four arguments: `(err, req, res, next)`. If you pass an argument to `next(err)` in any normal route, Express will bypass all standard middleware and jump straight to the nearest error handler.

Real-World Example: You create a central `errorHandler.js` at the bottom of your server file. Instead of writing `res.status(500).send()` in 50 different catch blocks, you simply write `catch (err) { next(err); }`. The central handler standardizes the error response and logs it.
Q20
How does the `Buffer` class allocate memory?
Intermediate

Buffers allocate raw memory *outside* the V8 JavaScript engine heap, meaning they aren’t subject to V8’s memory limits (usually ~1.5GB). `Buffer.alloc()` creates a zero-filled, safe buffer. `Buffer.allocUnsafe()` skips zero-filling, which is faster but may contain old, sensitive data from RAM.

Problem Scenario: If you use `Buffer.allocUnsafe(100)` and send it straight to an HTTP client without filling it first, you might accidentally leak encryption keys or passwords that were previously occupying that sector of RAM.
Q21
What is a Reverse Proxy and why put Node.js behind one?
Intermediate

A reverse proxy (like NGINX or HAProxy) sits in front of your Node server. Node is excellent at running application logic but mediocre at handling raw network tasks. The proxy handles SSL termination, gzip compression, serving static assets, and load balancing, freeing Node to focus strictly on API logic.

Real-World Example: Exposing a Node API directly to port 80/443 on the public internet is a security risk. NGINX absorbs slow-loris attacks and invalid HTTP requests before they even reach your Express app.
Q22
What is the role of PM2?
Intermediate

PM2 is a production process manager for Node.js. It ensures your application stays online 24/7 by automatically restarting it if it crashes. It also provides built-in load balancing (Cluster mode), log management, and zero-downtime reloads.

Real-World Example: Deploying an update. Without PM2, you stop the server, pull code, and start it—causing 10 seconds of downtime. With `pm2 reload`, PM2 spawns new workers with the new code, switches traffic to them, and kills the old ones, resulting in zero dropped user requests.
Q23
How would you architect a messaging system in Microservices using Node?
Intermediate

Microservices often use an Event-Driven Architecture via Message Brokers (like RabbitMQ or Apache Kafka). Instead of Service A making a synchronous HTTP request to Service B, Service A publishes an event to a queue, and Service B consumes it asynchronously.

Real-World Example: An Order Service successfully processes payment. It drops an `OrderCreated` message into RabbitMQ. The Email Service picks it up and sends a receipt, while the Inventory Service picks it up to reduce stock. If the Email service is down, the message stays in the queue until it comes back online.
Q24
What is gRPC and how does it compare to REST in Node.js?
Intermediate

gRPC is a high-performance RPC framework developed by Google. Unlike REST, which uses JSON over HTTP/1.1, gRPC uses Protocol Buffers (binary data) over HTTP/2. It is strictly typed and vastly faster, making it ideal for internal microservice-to-microservice communication.

Problem Scenario: Two internal Node microservices communicating via REST parsing massive JSON payloads will experience high CPU usage and latency. Switching to gRPC reduces payload size by ~60% and increases parsing speed dramatically.
Q25
What is an API Gateway?
Intermediate

An API Gateway is a server that acts as a single entry point into a system of multiple backend microservices. It handles cross-cutting concerns like authentication, routing, rate limiting, and analytics.

Real-World Example: A mobile app doesn’t need to know the IPs of your Auth Service, User Service, and Order Service. It makes all requests to `api.gateway.com`, and the Gateway (often built with Node/Express or Kong) verifies the token and routes the request to the correct internal Docker container.
Q26
How do you manage configuration for different environments (Dev, Staging, Prod)?
Intermediate

Use environment variables. You rely on the `NODE_ENV` variable to dictate the environment. Libraries like `dotenv` load local `.env` files, but in production, variables should be injected by the host (AWS Parameter Store, Kubernetes Secrets, or Docker Compose).

Problem Scenario: Hardcoding DB URLs based on `if (env === ‘prod’)` is an anti-pattern. Your code should strictly use `process.env.DATABASE_URL`. The environment host decides what that URL is, keeping your codebase environment-agnostic.
Q27
Explain the concept of Dependency Injection in Node.js.
Intermediate

Dependency Injection (DI) is a design pattern where an object receives its dependencies from the outside rather than creating them internally (e.g., using `require`). This decouples code and makes unit testing incredibly easy.

Real-World Example: Instead of importing a DB connection inside a User Controller, you pass the DB connection into the controller’s constructor. During testing, you can pass in a “Mock Database” object to test the controller logic without hitting a real database.
Q28
What is TDD and what tools do you use in Node.js?
Intermediate

Test-Driven Development (TDD) is writing tests before writing the actual code. In Node, standard tools include Jest or Mocha/Chai for unit and integration testing, and Supertest for testing Express HTTP endpoints.

Problem Scenario: You write a `user.spec.js` file using Supertest to assert that `POST /login` returns a 200 and a token. You wire this into a GitHub Actions CI pipeline. If a junior developer pushes code that breaks login, the CI pipeline fails, preventing the deployment.
Q29
How do you mock modules in Jest?
Intermediate

Jest provides `jest.mock()` to replace the actual implementation of a module with a dummy version. This isolates the function you are testing by preventing side effects like actual HTTP calls or database writes.

Real-World Example: If testing a function that sends an email via SendGrid, you do `jest.mock(‘sendgrid’)`. When the test runs, it verifies that the email function *would have* been called with the correct parameters, without actually sending a spam email to a real user.
Q30
What is a Memory Store vs Persistent Store for Sessions?
Intermediate

By default, `express-session` uses a MemoryStore, which stores session data in the Node process RAM. If the server restarts, all users are logged out. A Persistent Store (like `connect-redis` or `connect-pg-simple`) saves session data externally.

Problem Scenario: If you scale your Node app to 3 load-balanced instances, a user logging in on Instance 1 will be unauthorized if their next request is routed to Instance 2. Storing sessions centrally in Redis solves this.
Q31
Explain the concept of Database Indexing and how it relates to API speed.
Intermediate

An index is a data structure (usually a B-Tree) that improves the speed of data retrieval operations on a database table. If your Express API queries a table by `email`, applying an index to the `email` column prevents a slow “full table scan”.

Real-World Example: Your `/users/search` endpoint takes 5 seconds to query a table of 1 million users. After running `CREATE INDEX on users(email)`, the DB jumps straight to the record, and the API response time drops to 50ms.
Q32
What is a Database Transaction and how do you handle it in Node?
Intermediate

A transaction is a sequence of DB operations that must all succeed, or all fail completely (ACID properties). You start a transaction, run queries, and then either `COMMIT` or `ROLLBACK` on error.

Real-World Example: A bank transfer. You deduct $100 from User A, and add $100 to User B. If the Node server crashes exactly between these two queries, $100 is lost. Wrapping them in a transaction ensures that if the second query fails, the first is automatically rolled back.
Q33
How do you validate incoming API payloads?
Intermediate

Never trust client data. You should validate payloads at the route level before they reach your controllers. Popular libraries include Joi, Zod, or express-validator to enforce data types, lengths, and strict schemas.

Problem Scenario: An attacker sends a string instead of an integer for an `age` field, hoping to crash your DB query. A Zod schema checks the payload early and returns a clean 400 Bad Request to the client without touching your business logic.
Q34
What is CORS preflight?
Intermediate

Before sending a complex HTTP request (like PUT/DELETE, or containing custom headers), the browser automatically sends an `OPTIONS` request called a preflight. It asks the Node server, “Are you okay with me sending this request?”

Real-World Example: If your frontend sends a POST request with an `Authorization: Bearer ` header, the browser fires an OPTIONS request first. Your Express app (via the `cors` middleware) must respond with 204 OK and proper headers before the actual POST is allowed.
Q35
What is Server-Sent Events (SSE)?
Intermediate

SSE is a standard allowing a client to receive automatic updates from a server via an HTTP connection. Unlike WebSockets (which are bi-directional), SSE is uni-directional (Server to Client) and operates over standard HTTP.

Real-World Example: Building a live stock ticker. Setting headers to `Content-Type: text/event-stream` and `Connection: keep-alive` in Express allows you to continuously `res.write()` price updates to the client without the client needing to refresh or poll.
Q36
How do WebSockets differ from HTTP?
Intermediate

HTTP is stateless and strictly Request-Response (client must ask, server answers). WebSockets create a persistent, full-duplex TCP connection. Both the client and server can push messages to each other at any time.

Problem Scenario: In a multiplayer browser game, making 10 HTTP requests per second for player movement causes massive overhead from HTTP headers. WebSockets (via `socket.io`) send tiny, instant binary frames, making real-time gaming possible.
Q37
What is the “N+1” query problem and how do you solve it in Node (GraphQL/ORMs)?
Intermediate

The N+1 problem occurs when you query a list of items (1 query), and then iterate over that list, executing an additional query for each item (N queries). This crushes performance. It is solved using tools like DataLoader (batching) or DB joins.

Real-World Example: Fetching 50 blog posts, then looping through them to fetch the author for each = 51 database queries. Using `.populate(‘author’)` in Mongoose, or DataLoader in GraphQL, batches this into just 2 queries.
Q38
Why use a task queue like Bull/BullMQ?
Intermediate

Bull is a Redis-based queue for Node.js used to handle background jobs. You use it to offload tasks that take a long time and don’t require an immediate HTTP response to the user.

Real-World Example: A user clicks “Export Year History to CSV”. This takes 2 minutes. Instead of keeping the HTTP request open (which will timeout), you add a job to Bull, return a 202 Accepted, and have a background worker process the CSV and email it to the user.
Q39
How do you monitor the health of a Node.js application in production?
Intermediate

Health monitoring involves exposing a `/health` endpoint, collecting metrics (CPU, Memory, Request latency) using APM tools like Datadog, New Relic, or Prometheus, and setting up alerts for anomaly detection.

Problem Scenario: Kubernetes relies on a “Liveness Probe”. By pinging `your-api.com/health` every 10 seconds, Kubernetes knows if your app is stuck in an infinite loop. If the endpoint stops responding 200 OK, Kubernetes automatically destroys the pod and starts a fresh one.
Q40
What is CORS proxying and when would you use it?
Intermediate

When a frontend app needs data from a 3rd party API that does not support CORS, the browser will block the request. You can create a proxy route on your Node backend to fetch the data on behalf of the client (servers don’t enforce CORS on outbound requests) and return it to the frontend.

Real-World Example: Your React app needs to fetch an RSS feed from a legacy news site. The browser blocks it. You make your React app call `GET /api/news` on your Node server, and Node uses `axios` to fetch the XML, convert it to JSON, and send it to React.
Q41
Explain how the `require` caching mechanism works.
Intermediate

When you `require()` a module in Node, it is evaluated once, and the result is cached in `require.cache`. Subsequent calls to `require` for the same file will return the exact same cached object reference without re-executing the code.

Problem Scenario: If you export an instantiated object (e.g., `module.exports = new Database()`), every file that requires it shares the *exact same* connection state (a Singleton). If you need distinct instances, you must export the class or a factory function instead.
Q42
What is Content Negotiation?
Intermediate

Content negotiation is an HTTP mechanism where the client tells the server what format of data it expects (using the `Accept` header), and the server (e.g., Express) formats the response accordingly (JSON, XML, HTML).

Real-World Example: Express provides `req.accepts()`. If a web browser hits your route, you can return a rendered HTML view. If a mobile app hits the exact same route with `Accept: application/json`, you return a raw JSON object.
Q43
How do you handle file uploads in Express?
Intermediate

File uploads are sent using `multipart/form-data`. Express cannot parse this out of the box. You must use middleware like Multer or Busboy to intercept the binary stream, parse the file, and save it to disk or a cloud bucket.

Real-World Example: Using `multer({ dest: ‘uploads/’ })`, a user’s avatar image is intercepted, given a unique hash filename, and saved to the folder. Multer attaches the file metadata to `req.file` so your controller can save the path to the database.
Q44
What are the performance costs of JSON.parse / JSON.stringify?
Intermediate

Both methods are highly synchronous and CPU-intensive. Parsing massive JSON payloads (megabytes in size) will block the Event Loop entirely while V8 evaluates the string.

Problem Scenario: If you query 50,000 rows from Postgres and do `JSON.stringify(rows)`, the thread locks. For massive data transfers, you should use JSONStream (streaming the data chunk-by-chunk) rather than loading it all into memory.
Q45
Explain the concept of “Idempotency” in API design.
Intermediate

An API endpoint is idempotent if making multiple identical requests has the same effect as making a single request. `GET`, `PUT`, and `DELETE` should be idempotent. `POST` is typically not (it creates a new resource each time).

Real-World Example: If a user clicks “Checkout” but their WiFi drops, their phone might retry the `POST /charge` request. If not built carefully, they get charged twice. Using an Idempotency-Key in headers ensures the Node backend recognizes the duplicate and ignores the second charge.
Q46
How do you manage Node.js versions in a team environment?
Intermediate

You use a Node Version Manager like NVM (or Volta) and include a `.nvmrc` file at the root of your project containing the specific Node version (e.g., `v18.17.0`). Additionally, you lock engines in `package.json`.

Problem Scenario: Developer A is on Node 20 (which has native `fetch`) and pushes code. Developer B is on Node 16 and pulls the code; their server immediately crashes. A `.nvmrc` file forces the whole team to use identical environments.
Q47
What are ETags and how do they optimize API performance?
Intermediate

An ETag (Entity Tag) is an HTTP response header that provides a unique hash representing the requested resource. Express generates this automatically for responses.

Real-World Example: The client requests a user profile. Express sends it with `ETag: “1234”`. On the next request, the client sends `If-None-Match: “1234”`. If the profile hasn’t changed, Express intercepts this, stops generating JSON, and simply returns a 304 Not Modified, saving massive bandwidth.
Q48
Explain the purpose of the `os` module.
Intermediate

The `os` module provides operating system-related utility methods. It allows a Node app to query the underlying server for metrics like total memory, free memory, CPU architecture, and network interfaces.

Real-World Example: Before spinning up heavy worker threads or forking clusters, you use `os.cpus().length` to dynamically determine exactly how many cores are available on the specific AWS EC2 instance running the code.
Q49
Why use Prisma over traditional Mongoose/Sequelize ORMs?
Intermediate

Prisma is a Next-Generation ORM that replaces traditional class-based models with a custom schema file. It auto-generates a fully type-safe query builder customized exactly for your database, offering vastly superior TypeScript integration and auto-completion compared to older ORMs.

Real-World Example: In Sequelize, `const user = await User.findOne()` might return `any` type, leading to hidden runtime errors. In Prisma, hovering over `user` instantly shows exact properties based on your DB schema, catching errors at compile time.
Q50
What is the “Thundering Herd” problem and how do caching strategies fix it?
Intermediate

The Thundering Herd problem occurs when a highly trafficked cache key expires, and suddenly hundreds of concurrent requests all hit the primary database simultaneously to rebuild the cache, causing the DB to crash.

Problem Scenario: A popular news article’s Redis cache expires. 500 users hit the route. You fix this using “Cache Stampede Protection” (like Mutex locks or `redlock`), ensuring only the first request queries the database while the other 499 requests wait a few milliseconds for the new cache to be set.

Node.js Interview Questions: The Screening Round

50 Essential Beginner Node.js Interview Questions & Answers frequently asked by top MNCs.

Beginner Level (Q1 – Q50)

Q01
What is Node.js?
Beginner

Node.js is an open-source, cross-platform JavaScript runtime environment built on Chrome’s V8 JavaScript engine. It allows developers to execute JavaScript on the server-side, outside of a web browser.

Real-World Example: Imagine you want to build the backend for a chat application like WhatsApp. Node.js allows you to use JavaScript to handle thousands of users sending messages to your server in real-time.
Q02
How does Node.js differ from JavaScript in the browser?
Beginner

Browser JS interacts with the DOM (Document Object Model), handles UI events, and has no direct access to the OS. Node.js lacks the DOM but has direct access to the operating system, file system, and network interfaces via built-in modules.

Real-World Example: You cannot write a script in Chrome that silently reads a user’s local `C:/passwords.txt` file (for security). In Node.js, you can build a desktop app or server script that freely reads and writes to local hard drives.
Q03
What is the V8 Engine?
Beginner

V8 is Google’s open-source high-performance JavaScript and WebAssembly engine, written in C++. It compiles JavaScript directly into native machine code rather than interpreting it in real-time.

Problem Scenario: JS is naturally slow because it’s an interpreted language. Node.js leverages V8 to compile JS into fast machine code, allowing a Node server to perform complex calculations fast enough to serve thousands of concurrent API requests.
Q04
What is meant by “Non-blocking I/O”?
Beginner

Non-blocking I/O means that the Node.js process does not halt (block) when performing Input/Output operations like reading a file or querying a database. It delegates the task and continues executing subsequent code.

Real-World Example: Think of a waiter in a restaurant. Instead of waiting at the kitchen counter for your food to cook (blocking), the waiter submits your ticket and immediately goes to take orders from other tables (non-blocking).
Q05
Is Node.js single-threaded or multi-threaded?
Beginner

Node.js operates on a single main thread using an event loop. However, behind the scenes, it utilizes a C++ library called `libuv` which maintains a thread pool to handle heavy asynchronous I/O tasks.

Real-World Example: Your Express API has one main thread taking HTTP requests. If a request requires a heavy file system read, Node offloads it to the hidden thread pool, keeping the main thread free to accept new user logins.
Q06
What is the Event Loop?
Beginner

The Event Loop is the mechanism that allows Node.js to perform non-blocking I/O operations despite being single-threaded. It constantly monitors the call stack and callback queue, pushing resolved asynchronous callbacks onto the stack when it’s empty.

Real-World Example: It acts like an air traffic controller. It ensures standard code runs first, and queues up “delayed” tasks (like database responses) for landing only when the runway (call stack) is clear.
Q07
What is NPM?
Beginner

NPM stands for Node Package Manager. It consists of a massive online registry of open-source JavaScript tools/libraries, and a command-line utility used to install and manage these packages in your project.

Real-World Example: Instead of writing a complex date-formatting function from scratch, you run `npm install date-fns` to instantly download and use pre-written, tested code from the community.
Q08
What is the purpose of `package.json`?
Beginner

It is the manifest file of a Node.js project. It holds metadata like the project’s name, version, author, custom scripts, and most importantly, the lists of dependencies (packages) required to run the application.

Problem Scenario: If you share your code with a coworker, they don’t need your massive `node_modules` folder. They just need your `package.json`. They run `npm install`, and npm reads this file to download exact versions of every necessary library.
Q09
What is the difference between `dependencies` and `devDependencies`?
Beginner

`dependencies` are packages required for the application to run in production (e.g., Express, Mongoose). `devDependencies` are only needed for local development and testing (e.g., Jest, Nodemon, ESLint).

Real-World Example: A testing framework like Jest helps you test your app locally (`devDependency`). But when you deploy your app to an AWS server, the server only needs Express to run the API (`dependency`), ignoring Jest to save space and memory.
Q10
What is a Callback?
Beginner

A callback is a function passed as an argument into another function. In Node.js, callbacks are heavily used to execute code only after an asynchronous operation has completed.

Real-World Example: `fs.readFile(‘data.txt’, (err, data) => { console.log(data); });` — The anonymous function is the callback. Node goes to read the file, and “calls back” this function only when the hard drive finally returns the text.
Q11
What is “Callback Hell”?
Beginner

Callback Hell (or the Pyramid of Doom) occurs when multiple asynchronous operations depend on each other, leading to deeply nested, unreadable, and hard-to-maintain callback functions.

Problem Scenario: You need to 1) Find a user in a DB, then 2) Use their ID to find their orders, then 3) Use order IDs to find shipping details. Nesting these 3 callbacks makes the code indent into a shape of a sideways triangle, making bug-hunting a nightmare.
Q12
How do Promises solve Callback Hell?
Beginner

A Promise represents the eventual completion (or failure) of an asynchronous operation. Instead of nesting callbacks, Promises allow you to chain `.then()` and `.catch()` blocks, flattening the code structure.

Real-World Example: `getUser().then(getOrders).then(getShipping).catch(handleError)`. This reads top-to-bottom like a plain English sentence, making complex DB queries vastly easier to maintain.
Q13
What is `async/await`?
Beginner

Introduced in ES8, `async/await` is syntactic sugar over Promises. It allows developers to write asynchronous code that visually looks and behaves like synchronous, blocking code, while remaining non-blocking under the hood.

Real-World Example: Instead of `.then()`, you write `const user = await getUser();`. The execution logically pauses on that line until the DB returns the user, keeping your code exceptionally clean.
Q14
What is the `fs` module?
Beginner

The `fs` (File System) is a core Node.js module used to interact with the file system. It provides methods to read, write, update, delete, and rename files.

Problem Scenario: If you are building an error logging system, you use `fs.appendFile()` to write crash details into an `error.log` text file on the server’s hard drive so developers can review it later.
Q15
What is the difference between `fs.readFile` and `fs.readFileSync`?
Beginner

`readFile` is asynchronous and non-blocking, requiring a callback. `readFileSync` is synchronous and blocking; it completely halts the Node process until the file is fully read.

Problem Scenario: Never use `readFileSync` inside an API endpoint (e.g., when a user logs in). If the file takes 2 seconds to read, no other user in the world can access your server for those 2 seconds. Use it only for initial server startup configs.
Q16
What is the `path` module?
Beginner

The `path` module provides utilities for working with file and directory paths. It is essential because different operating systems use different path separators (Windows uses `\` while Linux/Mac uses `/`).

Real-World Example: `path.join(__dirname, ‘public’, ‘index.html’)` automatically constructs the correct file path regardless of whether your app is running on a developer’s Windows PC or an AWS Linux server.
Q17
What is the `http` module?
Beginner

The `http` module is a core module that allows Node.js to transfer data over the Hyper Text Transfer Protocol (HTTP). It can be used to create an HTTP server that listens to server ports and gives a response back to the client.

Real-World Example: While most developers use Express.js today, Express is actually just a framework built entirely on top of Node’s native `http.createServer()` method to handle web traffic.
Q18
What are EventEmitters?
Beginner

The `EventEmitter` class (from the `events` module) is used to trigger and listen to custom events. You use `.on()` to listen for an event and `.emit()` to trigger it.

Real-World Example: In a chat app backend, when a new socket connection is made, you can `emitter.emit(‘userJoined’, userData)`. Various distinct parts of your app listening to `.on(‘userJoined’)` can log the event, send a welcome email, and update the active user count independently.
Q19
What are Streams in Node.js?
Beginner

Streams are objects that let you read data from a source or write data to a destination in continuous, small chunks rather than loading the entire payload into RAM at once.

Problem Scenario: If you need to send a 2GB video file to a user, doing `fs.readFile` will load 2GB into the server’s RAM. If 10 users request it, the server crashes. Using `fs.createReadStream` sends the video frame-by-frame, using almost zero RAM.
Q20
What are the 4 types of Streams?
Beginner

1) Readable (read data), 2) Writable (write data), 3) Duplex (both read and write), 4) Transform (read, modify, and write).

Real-World Example: A video upload is a Readable stream from the user. You pipe it through a Transform stream to compress it (zip it). Finally, you pipe it to a Writable stream to save it to your hard drive.
Q21
What is a Buffer?
Beginner

A Buffer is a temporary storage spot for a chunk of raw binary data. It is primarily used by streams to hold data while it is being transferred from one place to another.

Real-World Example: Think of a Buffer like a roller coaster car. People (data bytes) load into the car. The car doesn’t move until it’s full (Buffer is full). Once full, it’s sent off to be processed, and an empty car takes its place.
Q22
What is the `process` object?
Beginner

The `process` object provides information about, and control over, the current Node.js process. It is a global object, meaning it is available everywhere without importing.

Real-World Example: You frequently use `process.env.PORT` to let cloud providers like Heroku or AWS assign a dynamic port to your app, or `process.exit(1)` to force the server to shut down if a critical database connection fails.
Q23
What is Express.js?
Beginner

Express.js is a minimal and flexible Node.js web application framework. It provides a robust set of features for building web and mobile APIs quickly, handling routing, requests, and responses efficiently.

Problem Scenario: Writing an API with Node’s raw `http` module requires manually parsing URLs and headers with hundreds of lines of code. Express reduces a full API endpoint down to a simple `app.get(‘/users’, (req, res) => {…})`.
Q24
What is Middleware in Express?
Beginner

Middleware functions are functions that have access to the request object (`req`), the response object (`res`), and the `next` middleware function in the application’s request-response cycle. They can execute code, make changes to req/res, or end the cycle.

Real-World Example: A bouncer at a club. The user requests to enter (`req`). The middleware checks if they have a valid JSON Web Token. If yes, it calls `next()` to let them into the route. If not, the middleware returns `res.status(401)` and kicks them out.
Q25
What is CORS?
Beginner

Cross-Origin Resource Sharing (CORS) is a security feature implemented by browsers. By default, a browser won’t let a frontend (e.g., your-react-app.com) make API calls to a backend on a different domain (e.g., your-node-api.com) unless the backend explicitly allows it via CORS headers.

Problem Scenario: If you try to fetch data from your Node API in a browser and get a red CORS error in the console, you fix it in Node by installing the `cors` package and adding `app.use(cors())` to explicitly allow cross-origin requests.
Q26
What is the difference between `req.params` and `req.query`?
Beginner

`req.params` contains route parameters (part of the URL path), while `req.query` contains URL query string parameters (everything after the `?` in the URL).

Real-World Example: In the URL `/users/123/shoes?color=blue`, `123` is a param (`req.params.id`), used to identify the specific user. `blue` is a query (`req.query.color`), used to filter the data.
Q27
How do you parse incoming JSON data in Express?
Beginner

You use the built-in middleware `express.json()`. Without this, if a client sends a JSON payload (like a signup form) via a POST request, `req.body` will be undefined.

Problem Scenario: Before an Express route can read `req.body.password` from a frontend React form, it must pass through `app.use(express.json())` which translates the raw HTTP byte stream into a readable JavaScript object.
Q28
What is `dotenv`?
Beginner

`dotenv` is a zero-dependency module that loads environment variables from a `.env` file into `process.env`.

Problem Scenario: You must never hardcode database passwords or AWS secret keys directly into your JavaScript files, because pushing to GitHub exposes them. You store them locally in a `.env` file (which is ignored by Git) and access them via `process.env.DB_PASS`.
Q29
What is `nodemon`?
Beginner

`nodemon` is a development utility that monitors your project for any file changes and automatically restarts your Node.js server.

Real-World Example: Without nodemon, every time you fix a typo in your API code, you must switch to the terminal, press `Ctrl+C` to stop the server, and type `node index.js` again. Nodemon does this instantly every time you hit Save (`Ctrl+S`).
Q30
How do you handle routing in Express?
Beginner

Express uses methods corresponding to HTTP verbs (e.g., `app.get()`, `app.post()`). For organizing complex apps, Express provides `express.Router()` to create modular, mountable route handlers.

Real-World Example: Instead of having 500 routes in `index.js`, you create a `users.route.js` file using `Router()`, and mount it in your main file using `app.use(‘/users’, userRoutes)`. This keeps large enterprise codebases clean.
Q31
What is an uncaught exception in Node.js?
Beginner

An uncaught exception is a JavaScript error that is thrown but not caught in a `try/catch` block. By default, this immediately crashes the Node.js process.

Problem Scenario: If you attempt to run `user.name.toUpperCase()` but `user` is accidentally null, Node throws an error. If there is no `try/catch`, your entire server goes offline for every user until it is manually restarted.
Q32
What is `Promise.all()`?
Beginner

`Promise.all()` takes an array of promises and runs them concurrently, returning a single Promise that resolves when all of the promises have resolved (or rejects if any one of them fails).

Real-World Example: A dashboard needs user profile data, recent orders, and notifications. Instead of waiting for them one by one (taking 3 seconds total), you put them in `Promise.all()`. They fetch simultaneously, taking only 1 second total.
Q33
Difference between CommonJS and ES Modules in Node?
Beginner

CommonJS uses `require()` and `module.exports` and is loaded synchronously. ES Modules (ESM) use `import` and `export`, are standard across browsers and modern JS, and are loaded asynchronously.

Problem Scenario: Historically Node only supported CommonJS. Now, to use modern `import express from ‘express’`, you must add `”type”: “module”` to your `package.json` file.
Q34
What happens if you block the Event Loop?
Beginner

Because Node is single-threaded, running a heavy, blocking synchronous task (like a massive mathematical `while` loop) prevents the Event Loop from processing any new incoming network requests.

Problem Scenario: If User A triggers a route that generates a massive PDF report synchronously (taking 10 seconds), the thread is blocked. User B, trying to simply log in at the same time, will see a loading spinner for 10 seconds until User A’s task finishes.
Q35
What is `setTimeout` vs `setImmediate`?
Beginner

`setTimeout(fn, 0)` schedules a script to run after a minimum threshold in ms. `setImmediate(fn)` schedules a script to run immediately after the current phase of the Event Loop (I/O polling) is complete.

Real-World Example: Use `setImmediate` when you have a heavy CPU operation that you want to break into smaller chunks, allowing I/O operations (like incoming requests) to squeeze in between the chunks so the server doesn’t freeze.
Q36
What is `process.nextTick()`?
Beginner

`process.nextTick()` schedules a callback function to be executed exactly after the current operation completes, but before the Event Loop moves on to the next phase.

Real-World Example: It acts like an absolute VIP pass. If you have an error event that absolutely must be handled before the server attempts to read any more files, `nextTick` forces that callback to execute immediately.
Q37
How do you connect a database to Node.js?
Beginner

Node interacts with databases using specific driver packages installed via npm. Common choices are `mongoose` for MongoDB, `pg` for PostgreSQL, or ORMs like `Prisma` or `Sequelize`.

Real-World Example: By installing `mongoose`, you can create rigid models for your NoSQL data and use simple methods like `User.find()` to fetch data without writing complex native queries.
Q38
What is JWT (JSON Web Token)?
Beginner

JWT is a standard for securely transmitting information between a client and a server as a JSON object. It is most commonly used for stateless user authentication.

Real-World Example: A user logs in. The Node server verifies the password and generates a JWT string containing their UserID, signed with a secret key. The frontend sends this token in headers on future requests. Express middleware verifies the signature to know who the user is without checking the DB.
Q39
Why use `bcrypt` for passwords?
Beginner

`bcrypt` is a library used to securely hash passwords. Hashing is a one-way mathematical function. You cannot “decrypt” a hash back to the original password.

Problem Scenario: If your DB is hacked, storing plain text passwords (`”password123″`) exposes all your users. `bcrypt` turns it into `$2b$10$xyz…`. Even if stolen, the hacker cannot reverse it to find the real password.
Q40
What is Helmet.js?
Beginner

Helmet is a middleware package for Express that automatically secures your application by setting various HTTP response headers.

Real-World Example: By simply adding `app.use(helmet())`, it hides the `X-Powered-By: Express` header (so hackers don’t know you use Node) and implements XSS protection headers to stop malicious script injections.
Q41
What is Semantic Versioning (SemVer)?
Beginner

SemVer is a versioning system used in `package.json` denoted by three numbers: MAJOR.MINOR.PATCH (e.g., `1.4.2`).

Real-World Example: `PATCH` (1.4.3) means bug fixes. `MINOR` (1.5.0) means new features but backwards compatible. `MAJOR` (2.0.0) means breaking changes. Knowing this prevents you from updating an npm package that breaks your entire API.
Q42
What is the purpose of `package-lock.json`?
Beginner

While `package.json` specifies acceptable version ranges (e.g., `^1.4.0`), `package-lock.json` records the exact, precise version of every dependency and sub-dependency that was actually installed.

Problem Scenario: “It works on my machine but crashes in production.” This happens when devs have slightly different minor versions of a library. The lock file forces all developers and deployment servers to install identical byte-for-byte dependencies.
Q43
What is the `cluster` module?
Beginner

The `cluster` module allows you to easily create child processes (workers) that run simultaneously and share the same server port. This takes advantage of multi-core systems.

Real-World Example: Node is single-threaded. If you run it on an 8-core AWS server, 7 cores are asleep. Using `cluster`, you fork your app 8 times. Now 8 Node instances share the traffic, handling 8 times as many requests simultaneously.
Q44
What are Worker Threads?
Beginner

Introduced to handle CPU-intensive tasks, the `worker_threads` module allows Node.js to execute JavaScript in parallel using isolated V8 environments, without blocking the main event loop.

Problem Scenario: If your app needs to resize uploaded images (heavy CPU math), doing it on the main thread blocks all HTTP requests. Sending the task to a Worker Thread keeps the main thread fast and responsive.
Q45
How do you prevent SQL Injection / NoSQL Injection in Node?
Beginner

Never concatenate raw user input directly into database query strings. Always use parameterized queries (prepared statements) or use an ORM/ODM (like Mongoose or Prisma) which sanitizes inputs automatically.

Real-World Example: In Postgres via Node, instead of `query(“SELECT * FROM users WHERE email = ‘” + req.body.email + “‘”)`, you use parameterization: `query(“SELECT * FROM users WHERE email = $1”, [req.body.email])` to render malicious SQL syntax harmless.
Q46
How do you debug a Node.js application?
Beginner

While `console.log()` is common, professional debugging is done by starting Node with the `–inspect` flag, or by using the built-in debugging tools in an IDE like VS Code to set breakpoints.

Real-World Example: By clicking the margin in VS Code to create a red dot (breakpoint) and attaching the debugger, the server will freeze at that exact line of code during a request, allowing you to inspect variable values in real-time.
Q47
What is an API?
Beginner

Application Programming Interface. In the context of Node, it’s a set of URL endpoints that allow frontend applications (like React, or a mobile app) to communicate with your backend logic and database.

Real-World Example: An iOS app doesn’t connect to a database directly. It makes an HTTP request to your Node API at `api.yoursite.com/users`, and your Node API handles the secure database fetching and returns JSON.
Q48
What is REST?
Beginner

Representational State Transfer (REST) is a software architectural style. A RESTful API relies on standard HTTP methods (GET, POST, PUT, DELETE) linked to specific URLs (resources) in a stateless manner.

Real-World Example: `GET /articles` fetches all articles. `POST /articles` creates one. `DELETE /articles/5` deletes article #5. It relies on standard conventions that any frontend developer will immediately understand.
Q49
What is global installation of an npm package?
Beginner

By using the `-g` flag (`npm install -g package-name`), the package is installed on your operating system globally, rather than in the local `node_modules` of a specific project. This is usually reserved for CLI tools.

Real-World Example: You install `nodemon` or the `angular-cli` globally so you can type those commands directly into any terminal window on your machine, regardless of what folder you are in.
Q50
What are Memory Leaks in Node.js?
Beginner

A memory leak occurs when a Node app allocates memory (RAM) but fails to release it back to the OS when it’s no longer needed (garbage collection failure). Over time, RAM fills up and the server crashes.

Problem Scenario: Storing user session data in a global JavaScript array `const sessions = []` instead of a database like Redis. Every user login adds to the array. The array never clears. Eventually, it consumes all 2GB of server RAM and the process dies.