Advanced concepts in Node.js & Express
Libuv: The Engine Behind Node.js Async I/O
Libuv is the C library that powers Node.js's non-blocking I/O. It translates JavaScript's event loop into high-performance async calls for the host OS. The footgun is thinking this makes Node multi-threaded; it uses an event loop and a thread pool.
Worker Threads: True Parallelism in Node.js
Worker threads give Node.js a separate brain for heavy lifting, letting you run CPU-intensive code without blocking the main event loop. Use them for tasks like image processing, not I/O. The footgun is assuming memory is shared; it isn't.
Node.js Cluster: Scaling on a Single Machine
The cluster module turns a single-threaded Node.js app into a multi-process server that uses all CPU cores. It's ideal for scaling network applications on one machine by sharing a single port.
Node.js Circular Dependencies: The Unfinished Export
When module A requires B, and B requires A, Node.js avoids an infinite loop by returning an unfinished version of one module's exports. This happens in complex apps with tightly coupled modules. The code doesn't crash; it fails later with a TypeError.

NPM Scopes: Namespacing Packages to Avoid Collisions
NPM scopes act like a personal folder for your packages, using the @scope/package format to avoid name collisions. They are essential for publishing private packages for your team or grouping related public ones.

Promise.race(): First Promise to Settle Wins
Promise.race() returns a promise that mirrors the outcome of the first promise in a set to finish—the winner takes all, whether it resolves or rejects. Use it to set a timeout on a network request.

Promise.allSettled(): Never Fail a Batch of Promises
Promise.allSettled() waits for every promise in a set to finish, success or fail, without short-circuiting. Use it for independent tasks, like multiple API calls, where you need the outcome of each.

Promise.any(): Get the Fastest Successful Result
Promise.any() is a race where only finishers count. It returns the value of the first promise to succeed, ignoring any that fail. Use it to query redundant endpoints and take the first successful response.

Top-Level Await: `await` Without an `async` Function
Top-level await lets you use await directly in an ES module, no async function needed. Use it to initialize resources like database connections on startup. The footgun: the entire module's execution blocks until the promise resolves, delaying startup.
Hashing Data with Node.js's `crypto` Module
Hashing creates a unique, fixed-size fingerprint of data. It's a one-way process used to verify data integrity or store passwords securely without saving the plain text. The footgun is using weak algorithms like MD5 or SHA1 for security-sensitive tasks.
Node's zlib Module: Trading CPU for Bandwidth
Node's zlib module trades CPU cycles for network bandwidth by shrinking data with algorithms like Gzip and Brotli. Use it to compress large API responses or files before sending them. The main footgun: never use synchronous ...Sync methods in a server.
Node.js DNS: lookup vs. resolve
Node.js splits DNS into two paths: dns.lookup uses getaddrinfo for IPs, while the dns.resolve family fetches records like MX or TXT. Use lookup for connections and the resolve family for service discovery.

Express Error Middleware: Your App's Safety Net
Express error middleware is a safety net that intercepts unhandled errors, preventing crashes. It's used to centralize logging and format consistent error responses. The biggest footgun is placement: it must be defined *after* all other routes and middleware.

Idempotency in REST APIs: Safe to Retry?
An idempotent API request means sending it once or 100 times has the same effect on the server's state. GET, PUT, and DELETE are idempotent, making them safe to retry. POST is not, so retrying can create duplicates.
API Rate Limiting: Protecting Your Express Endpoints
Rate limiting acts as a bouncer for your API, preventing any single user from overwhelming it. It's crucial for public APIs and sensitive endpoints like password resets to block abuse. The default in-memory store won't work across multiple server instances.
HATEOAS: Let Your API Tell You What's Next
HATEOAS makes an API self-discoverable, like a website where you click links instead of guessing URLs. The server's response includes links for the next possible actions, decoupling the client from hardcoded endpoints.
Sequelize Transactions: All-or-Nothing Database Writes
A Sequelize transaction is a safety wrapper for database queries, ensuring they all succeed or none do. Use it for multi-step operations like creating a user and profile.

Mongoose Population: Linking Documents Across Collections
Mongoose's populate() acts like a client-side JOIN, replacing document IDs with actual documents from other collections. It's ideal for linking related data, like a blog post's author.
Sequelize Scopes: Reusable Query Shortcuts
Sequelize scopes are named shortcuts for common query conditions, letting you define where or include clauses once and reuse them. Use them to keep code DRY, like an active scope. The footgun: a defaultScope is always on unless you call .unscoped().
OAuth 2.0: Delegated Authorization, Not Authentication
Think of OAuth 2.0 as a valet key for your data. It lets a third-party app access specific resources on your behalf without you sharing your password. It's used for "Log in with Google" or letting an app access your photos.
We are hiring for this. Every open role lists the topics its interview covers, so you can prepare for the real thing rather than guessing.
See open roles