~/teardowns/TD-043.md
←Back to teardowns
# TD-043HighRuntime

The Read That Stopped the Whole Server

readFileSync on the request thread blocks every other request

Published Oct 29, 2026

Executive Summary

A vibe-coded Express endpoint reads the product catalog with readFileSync() and parses it inline. Node runs JavaScript on one thread, so while the file is read and parsed, no other request can be processed. One slow read stalls the entire server for every user.

The Prompt

“Add an endpoint that reads the product catalog and returns the count for the dashboard.”

The Flaw

Node runs JavaScript on a single thread. readFileSync() and JSON.parse() of a large file block that thread for the entire read and parse — while they run, no other request is processed. Under any concurrency, every request queues behind this one, so one slow disk read stalls the whole server, not just the caller.

Risk & Impact

[Availability] A single slow request freezes the entire server. Latency spikes and timeouts hit every user, not just the one calling this endpoint.

Cost: The whole service stalls on every catalog read — a textbook event-loop outage that only appears under real load.

Code Comparison

❌ Vulnerable (AI generated)

catalog.jsjavascript
1
2
3
4
5
6
7
8
const fs = require('fs');
app.get('/catalog/count', (req, res) => {
const raw = fs.readFileSync('./products.json'); // blocks the event loop
const products = JSON.parse(raw);
res.json({ count: products.length });
});

The Fix

Use the async fs API (fs/promises) so the event loop keeps serving other requests, and cache the result so the file is not re-read per request.

Prevention

  • [linter] ESLint's no-sync rule flags readFileSync/readdirSync/etc. in request handlers.
  • [ci] A load test (or a test that fires concurrent requests during a slow read) must show the server still answering.
  • [manual] Ask for a hardened implementation, not a prototype (rule 5), and load-test before shipping (rule 9).

Why This Happened

Root cause: the prompt omitted Rule 5 and Rule 9 — the guardrails that would have caught this. See the full guide →

Sources

Is your codebase vulnerable to this?

Run Diagnostic on My Project →