
Explore how Node.js executes code through the event loop, detailing the synchronous start, microtask and macro phase processes, and the roles of promises, process.nextTick, setImmediate, and I/O callbacks.
Understand how Node.js schedules code across the event loop, microtasks, and I/O phases to determine the exact console log order with setTimeout, setImmediate, and promises.
Analyze how async console.logs order themselves by rewriting the code with promises to reveal the node event loop, microtasks queue, and check phase, with setTimeout and setImmediate scheduling.
Drive asynchronous task handling with node.js, including api calls and database requests, without blocking the main thread. Leverage the single threaded event loop and libuv to offload blocking work.
Explore the pros of Node.js architecture: JavaScript ease and event-driven, non-blocking I/O. Assess cons like single-threaded limits and multi-core challenges within microservices and npm ecosystem.
Contrast io bound tasks, limited by io device speed and data transfer waiting, with cpu bound tasks processed by Libuv thread pool, up to four threads, causing bottlenecks if overloaded.
Explain blocking versus non-blocking operations in node.js, noting I/O handling, CPU-bound tasks, and how the event loop uses asynchronous callbacks.
Cache frequently used data in memory and use memory mapped files to reduce I/O, while employing connection pooling, multi-processing with cluster, and optimized queries with streams and microservices.
Learn how to improve cpu-bound task performance in node apps by using worker threads or child processes, with benchmarks and overhead considerations.
Learn how blocking the event loop harms performance in NodeJS, and how worker threads prevent unresponsiveness by offloading tasks. Identify which synchronous NodeJS APIs—encryption, compression, and file system—can block.
Minimize blocking code by avoiding synchronous database access and CPU-heavy tasks; use async patterns with promises, async/await, or simple callbacks, and break large buffers into chunks with streams.
Libuv delegates io and async cpu tasks to the thread pool during the poll phase; tasks are assigned when a worker is free, otherwise queued.
Explore how Node.js achieves concurrency with a single-threaded event loop and non-blocking I/O, and how parallelism emerges via libuv thread pool and worker threads for true multi-thread execution.
Discover how libuv's worker pool powers encryption, compression, file system, and DNS tasks in Node.js, and learn when to use async versus sync APIs to balance CPU and I/O workloads.
Explain how a promise initializes in the execution context, runs its executor immediately, starts asynchronous work non-blocking, and transitions through pending to fulfillment or rejection via the V8 microtask queue.
Learn how Node.js cluster mode uses a built-in load balancer to spawn multiple workers on a single port, leveraging CPU cores for faster requests, and how PM2 offers production-grade clustering.
PM2, an open source production-grade cli for running Node.js applications in a cluster, runs multiple processes with a built-in load balancer, zero-downtime reloads, and graceful startups.
PM2 is a production process manager for Node.js with built-in load balancing, automatic restarts, and cluster mode support, enabling horizontal scaling, real-time monitoring, and log consolidation for multi-app deployments.
Compare cluster mode and worker threads in Node.js, including PM2 for load balancing across cores, and offloading CPU intensive tasks to workers for parallel processing.
Explore how worker threads run JavaScript in parallel on CPU threads, with V8 isolates and Libuv, enabling shared memory and concurrency, plus trade-offs like risk of crashes and synchronization.
Compare child processes and worker threads in Node.js, noting isolation of child processes and inter-thread communication with shared memory in threads, plus cluster's built-in load balancer and port binding issues.
Explore how npm manages JavaScript packages with package.json and package-lock.json, detailing dependencies, devDependencies, scripts, main, engines, and how npmrc configures registry, proxy, SSL, and exact version saving.
Update package-lock.json is possible but not advisable; rely on npm install to keep dependencies consistent and reproducible, and use npm update to upgrade a dependency when needed.
Learn how npm resolves dependencies by installing top-level packages from package.json, recursively processing transitive dependencies, resolving conflicts at the highest level, and updating package-lock.json to lock exact versions.
Explore how peer dependencies in npm relate host libraries and plugins, including automatic installation since npm 7, optional peers, and compatibility between NestJS core and Platform Express.
Semantic versioning uses major, minor, and patch numbers to signal changes: major releases bring breaking changes, minor adds features, patches fix bugs, and check changelogs and run tests before deployment.
Update dependencies carefully, exclude dev dependencies from production, run smoke and automated regression tests, use dependabot, audit with npm, and integrate static analysis in your ci/cd pipeline.
Explore how Node.js exit codes signal termination, with zero for success and non-zero for failures, and how process.exit signals termination with the provided code and exit listeners run cleanup.
Learn robust error handling in NodeJS applications by mastering try/catch with promises, finally, and proper rejection handling; implement error handling middleware in Express and NestJS, and emphasize logging and TypeScript.
Create custom errors in NodeJS by extending the built-in error via inheritance to expose precise location and context, including a simple error and a builder-pattern, chainable auth error for debugging.
Explore the test pyramid guiding unit, integration, and end-to-end tests in Node.js, with Jest, Mocha, Jasmine, Supertest, Chai, Cypress, and Puppeteer shaping each level.
Simulate production conditions with requests per second, concurrent connections, and varying payloads to benchmark Node.js apps, using ApacheBench or Locust and analyzing bottlenecks for optimization.
Learn the differences between mocking, spying, and stubs, and how to use each in jest to isolate dependencies, track function calls, and substitute static behavior.
Explore spying, mocking, and stubbing with a fake GCP storage service and interface. Learn to verify external calls and control mock return values using jest in a TypeScript test setup.
Practice unit tests that focus on a single function or module to ensure isolated, deterministic results, covering success, failure, and edge cases with descriptive names and mocked dependencies.
Explore integration testing best practices for Node.js, focusing on interactions between components, realistic test data, isolation through mocks, and scenarios covering success, error, and concurrency.
Explain the difference between readFile and createReadStream in Node.js, focusing on memory usage and chunked processing; readFile loads the entire file, while createReadStream streams in chunks.
Explore how buffers in node.js are fixed-size memory containers for binary data, enabling file and network i/o and encoding with utf8, utf16, latin1, base64, and hex.
Explore Node.js streams as non-blocking, memory-efficient abstractions for processing data in chunks. Learn about readable, writable, duplex, and transform streams and their event-driven behavior.
Explore the four native Node.js streams—writable, readable, duplex, and transform—and see how data is written, read, transformed, and piped in practical examples like uppercase conversion.
Explore how streams optimize I/O performance by buffering data, reducing disk writes, and using drain events to drain the internal buffer, achieving far faster writes than synchronous approaches.
High watermark defines a stream’s internal buffer size in bytes; adjust read and write stream values and monitor readable and writable length to manage data flow.
Learn how the data event delivers data chunks and how to attach a listener with a callback, then examine error, end, and close events and resource management to prevent leaks.
Learn how writable streams buffer data, trigger IO writes when the buffer drains or reaches its high watermark, and emit drain, finish, and close events to manage resources.
Explain back pressure in NodeJS streams, showing how buffers grow when producers outrun consumers, and how to manage it by awaiting drain with a one-time listener on a writable stream.
Learn how to copy huge files with node.js using streams while managing back pressure, pausing and resuming on drain, and using pipe for automatic safe data flow.
Master streaming data in Node.js by handling range requests, creating a readable stream, and piping it to the response to deliver 206 partial content with range headers.
Explore how piping in Node.js connects a readable stream to a writable stream, enabling efficient data transfer without loading all data into memory, and handling back pressure in streams.
Explore why the plain pipe API in Node.js lacks automatic error handling and can cause memory leaks; learn how the pipeline API catches errors and safely destroys affected streams.
Learn how the NodeJS pipeline forwards errors, cleans up, and provides a completion callback, resolving pipe’s error handling with a readable first, a writable last, and duplex or transform intermediates.
Learn how to implement a custom Node.js stream by extending a base stream, overriding underscored methods, and avoiding overwriting native APIs while safely handling reads, writes, and events.
Explore the main http methods and their top use cases, including get, post, put, patch, delete, head and options, plus connect and trace, with notes on idempotence and request bodies.
Explore which http methods are idempotent or safe, including get, head, options, trace, put, and delete, and why post is not, with patch nuances.
Learn how http status code classes map to client and server responses, with examples of common codes like 200, 201, 204, 206, 301–302, 304, 400–405, 500–503.
Understand how HTTP requests include method, URL, path parameters, query parameters, headers, body, and cookies for session management and identifying resources.
explains how data contracts define api data structure, formats, and semantics; covers validation on client and server, versioning, and documentation with swagger or open api for clear, consistent interfaces.
Master flat data structures, wrap responses in a data property, and use consistent naming, status codes, pagination, structured errors, and caching headers for scalable apis.
Explore how HTTP headers enable client-server meta communication, control caching and security with cache-control and strict-transport-security, and drive content negotiation via Accept and Content-Type headers.
Explore how cache-control and expires manage resource caching to boost performance. Apply security headers such as content security policy, strict-transport-security, x-content-type-options, and x-frame-options to protect against threats.
Explore representational state transfer, a language-agnostic, stateless API style using http methods and json, with xml or text options and soap contrasts, with security considerations.
Design restful endpoints using standard HTTP methods and status codes, with a versioned API prefix, plural resource names, and route parameters, while avoiding verbs and enabling filtering with query params.
GraphQL is a specification for querying and manipulating data that solves over fetching and under fetching with a single post endpoint, a strict schema, and language-agnostic JSON responses.
GraphQL demands schemas and resolvers, increasing development effort and updates versus REST. It complicates debugging and raises security risks from nested queries, requiring depth and rate limiting.
Discover how a GraphQL resolver populates data for a schema field, using Express and Nestjs with Apollo. See real examples with curl requests and a schema-first approach.
Compare REST and GraphQL by project size, data needs, and architecture; REST suits simple, public APIs, while GraphQL handles complex data with a unified microservices API layer.
Interviews can be quite stressful. For some reason, you often freeze or struggle to verbalise the concepts with which you work on the daily basis. Although you have enough coding and design knowledge, you might not be as efficient presenting this knowledge as using it in your projects.
Preparation is the best type of effort you can put in, to put your best foot forward in an interview setting. Apart from coding skills, you also need to be able to verbalise the concepts you work with and be able to clearly articulate how they work and what problems they address.
This is where this course comes in. I gathered 100+ actual Node.js interview questions either I personally received or my colleagues did. Although I wouldn't do bad answering those in the actual interview, I often left out important details. Especially when asked about intimate knowledge of how Node.js operates and what makes it so good for the web, database related questions and some good practices around working with them and many more. Here's a glimpse of some of the more important topics covered in this course:
Node.js event loop
Cluster mode (+ PM2), Child Process and Worker Threads
NPM dependencies
stubbing, spying and mocking in testing
Buffer & Stream for working with data
pitfalls of streams when working with a lot of data
data streaming in Node.js
designing data contracts and http responses
REST v GraphQL
CommonJS v ES Modules
webserver building blocks - middleware, interceptor, router, controller, service
relational v non-relational databases
database migrations
SQL anti-patterns
multi-stage Dockerfiles
managing tasks in distributed multi-pod microservice
how to mitigate risk of SQL injection
and MUCH more!
This course is meant to prepare you for such questions by going as deep as needed into each concept, understanding the context of questions, understanding the underlying technology used to address the problem asked by the interviewer and providing clear recommendations. In the end, there are no perfect solutions, there are just trade-offs. To find the right solution, you need to understand those trade-offs.
I know I will be using this course to prepare for my Node.js interviews. I also plan on adding new questions from my own interviews and others’. I would love to add yours too!
Another valuable resource is course repository with running code examples for a lot of questions. That’s the playground where theory meets practice. Each example is a standalone recipe on how to use a component or pattern in practice.
I am not saying this course is going to make you a Node.js expert. But I'm also not saying it won't.