Skip to solution
easyPhone Screen

What is the difference between readFile and createReadStream in Node.js?

883 views
01

Understand the problem

Question presented to candidate: "You need to serve a 2GB video file from an HTTP endpoint. Would you use fs.readFile or fs.createReadStream, and what specifically goes wrong with the other choice?"

What a strong answer should cover:

  • fs.readFile (and fs.promises.readFile) reads the entire file into memory and delivers it as a single callback/Promise resolution carrying one complete Buffer — simple to use, but memory usage scales directly with file size.
  • fs.createReadStream reads the file incrementally, delivering it across many smaller chunks (sized by highWaterMark, default 64KB) via 'data' events (or async iteration, or piped directly to a writable) — memory usage stays roughly constant regardless of total file size.
  • 📌 The concrete, measured difference: the identical 20MB file arrived as one readFile callback carrying the full 20MB buffer, versus 320 separate 'data' events from createReadStream with a 64KB highWaterMark — the same total bytes, delivered in a fundamentally different shape.
  • The practical rule: readFile is fine for files small relative to available memory where the whole content is needed at once anyway (a config file, a small template). createReadStream — usually piped directly to an HTTP response or another writable — is correct for large files, especially ones served over a network, where loading the entire file into memory first is wasteful or outright impossible at scale.
  • Streaming also enables starting the response before the whole file is read — a client receiving a large file over createReadStream.pipe(res)` starts receiving bytes almost immediately, rather than waiting for the entire file to load into memory first.
  • A precise answer connects this to backpressure: a stream naturally slows its internal reads to match how fast the destination can consume data (covered fully in the dedicated stream.pipeline()/backpressure questions); readFile has no equivalent concept — it either succeeds with the whole buffer or fails entirely.

Clarifying questions expected:

  • "How large is the file relative to the process's available memory, and how many concurrent requests need to read it?" — this is the actual deciding factor, not a blanket rule.
  • "Does the whole file need to be in memory at once for further synchronous processing, or can it be handled chunk by chunk?" — decides whether streaming is even applicable to the use case.

Code / implementation expected: Yes — the measured chunk/callback count difference for the identical file is the concrete, convincing part of the answer.

file-systemstreamsmemory
02

Attempt it yourself

Sketch your approach before reading the solution — that's what interviews test.

Nudge consolestandby

Stuck? Beam a request up — the console returns a conceptual nudge that guides your logic without spoiling the implementation.

03

Study the solution

Target Audience: Engineers preparing for Node.js phone screens — assumes very basic fs module familiarity. Difficulty: Easy

How to read this doc: Concepts are explained in plain language first, then tagged with 📌 Interview term:. The numbers below came from **actually reading a real 20MB

Solution ready — 2 min read

Classified // press E to declassify

04

Read the code

The same 20MB file: readFile's single callback vs createReadStream's 320 chunked events, measured
const fs = require("fs");
const BIG = "big2.bin"; // a real 20MB file on disk

fs.readFile(BIG, (err, data) => {
  console.log("readFile callback fired ONCE, length:", data.length);
  // readFile callback fired ONCE with the full buffer, length: 20971520

  let chunks = 0, totalBytes = 0;
  const stream = fs.createReadStream(BIG, { highWaterMark: 64 * 1024 });
  stream.on("data", (chunk) => { chunks++; totalBytes += chunk.length; });
  stream.on("end", () => {
    console.log(`createReadStream delivered ${totalBytes} bytes across ${chunks} events`);
    // createReadStream delivered 20971520 bytes across 320 separate events
  });
});
05

Join the discussion

Discussion (0)

Sign in to join the discussion.

No responses yet. Be the first to share what you think.

Transmission complete // awaiting log

KEEP THE
STREAK ALIVE.

Dossier 8 of 152 decoded in the Node.js track. One more won't hurt.

Back to track