Question presented to candidate: "You call require('./db') from three different files in the same process. Do you get three separate module instances, or one shared instance — and how would you actually prove which one happens?"
What a strong answer should cover:
- Every CommonJS file is wrapped by Node in an implicit function before execution, receiving five parameters:
exports,require,module,__filename,__dirname— this is why those identifiers are available inside any.jsfile without an explicit import. - 📌 The module cache is the key mechanism:
require()resolves a specifier to an absolute file path, and if that exact path has already been loaded once in this process,require()returns the cachedmodule.exportsobject instead of re-running the file — verifiably the SAME object reference (===), not just an equal-looking copy. - This means a module's top-level state (a counter, a cached connection, a singleton) is naturally shared across every file that
require()s it in the same process — this is both the mechanism behind the common "singleton via module" pattern, and a source of surprising bugs when that sharing is unintended. module.exports(the object actually returned byrequire()) and the bareexportsvariable start out pointing at the same object, but reassigningexports = {...}breaks that link — only reassigningmodule.exportsitself changes whatrequire()actually returns. This is a common, verifiable source of "why did my export not show up" bugs.- Node resolves a bare specifier like
require("./db")by trying, in order, an exact file match, then common extensions (.js,.json,.node), then a directory with anindex.jsor a"main"field — a good answer names this resolution order rather than treating it as unspecified magic. - The module cache is keyed by the resolved absolute path — two different relative specifiers that resolve to the same file (e.g. from two different directories) still hit the same cache entry, and the module still executes only once.
Clarifying questions expected:
- "Is the concern about state sharing being a bug, or intentionally relying on the singleton pattern?" — the caching behavior is the same either way; the framing of "is this a problem" differs.
- "CommonJS specifically, or does the codebase also use ES Modules?" — the caching mechanism and its guarantees differ subtly between the two systems, covered in the dedicated CommonJS-vs-ESM question.
Code / implementation expected: Yes — actually requiring the same file twice and showing the returned objects are identical and share mutated state is the concrete, convincing proof here.