The Hard Parts

Intro

The Hard Parts is a collection of certification-level questions designed to test real understanding of how software actually behaves at runtime.

These articles are not tutorials.
They are not syntax explanations.
They exist to expose the mental models that quietly break systems as they scale.

Each article starts with a short code snippet and a single question.
If you can answer it confidently, you’ve probably been burned by it before.


What This Category Is

  • Language-agnostic over time (not limited to JavaScript or TypeScript)
  • Focused on behavior, not style
  • Grounded in real production failure modes
  • Written from a senior engineer’s point of view

What This Category Is Not

  • “Gotchas”
  • Trick questions
  • Interview brain teasers
  • Academic theory

If a problem doesn’t cause real pain in real systems, it doesn’t belong here.


Javascript/Typescript Articles

Async, Await, and the Event Loop

  1. Why async + forEach Lies to You
  2. What Actually Happens When Promise.all Fails
  3. Why try/catch Doesn’t Catch This Async Error
  4. Why await Changes Execution Order Even When Nothing Is Waiting
  5. What Finishes First: the Function or the Async Work?
  6. Is Promise Order Guaranteed?
  7. Why This Async IIFE Doesn’t Do What You Think
  8. Why setTimeout(fn, 0) Is Never Immediate
  9. Why This Loop Logs the Same Value Three Times
  10. Where Does This Async Error Actually Go?

Concurrency, Coordination, and Failure

  1. Who Owns Completion When Nothing Is Awaited?
  2. What Survives a Failed Promise.all?
  3. What Happens to the Losing Promise in Promise.race?
  4. How Many Promises Exist in This async Function?
  5. When Does a Rejection Become Unhandled?
  6. Why Mixing then() and await Breaks Error Flow
  7. When Parallelizing Async Work Is Incorrect
  8. Why This Error Crashes Production but Not Tests
  9. How Microtasks Can Starve the Event Loop
  10. Why “Single-Threaded” Is a Misleading Description

Closures, Scope, and Lifetime

  1. When Does This Closure Actually Get Released?
  2. Why var and let Behave Differently in Loops
  3. How Closures Quietly Create Memory Leaks
  4. Why This Closure Returns Stale Data
  5. When Variables Are Shared Across Iterations
  6. Why Moving Code Outside a Closure Fixes the Bug
  7. How Closures Hide Shared Mutable State
  8. Why Async Code Makes Closures Harder to Reason About
  9. What Exactly Is Captured in This Closure?
  10. Why “Just Put It in a Closure” Is Dangerous Advice

Objects, Identity, and Mutation

  1. Who Owns This Mutation?
  2. Why This Shallow Copy Fails
  3. Why Object Identity Matters More Than Shape
  4. How Two Callers Mutate the Same Object Without Knowing
  5. Why Immutability Is a Discipline, Not a Feature
  6. What Breaks When You Mutate Data You Didn’t Create
  7. Why This Mutation Makes Debugging Impossible
  8. What === Is Actually Comparing Here
  9. Why Object.freeze Isn’t Enough
  10. Why Copying Data Doesn’t Isolate Behavior

Type Systems and False Safety

  1. Where TypeScript Stops Protecting You
  2. Why Structural Typing Is Both Powerful and Dangerous
  3. How This Code Is Type-Correct but Logically Wrong
  4. Why Types Disappear at Runtime — and Why That Matters
  5. When Inference Actively Hides a Bug
  6. Why Widening Types Is Riskier Than any
  7. How This Assertion Breaks an Invariant
  8. Why as Turns Into Technical Debt
  9. Type Safety vs Behavioral Correctness
  10. Why Adding More Types Can Reduce Reliability

How to Read These Articles

Read them slowly.
Run the code mentally.
If your first answer is wrong, that’s the point.

These are the problems that don’t look hard — until they are.

Scroll to Top