Lifetime and Process Memory

4.The Function That Packed a Suitcase

A

In this chapter

We'll separate two ideas people mix up — scope (where a name can be seen) and lifetime (how long the data exists) — see how a closure keeps data alive, and look at the four sections every process's memory is divided into: code, data, stack and heap.

12–14 min

The Problem in Real Life

Anna points at the timer line: setTimeout(() => releaseSeat(seatId), HOLD_DURATION_MS). "seatId is a local variable. It's only visible inside holdSeat. When holdSeat ends, its stack tray is gone. So how can the timer still use seatId ten minutes later?"

John nods. "Because you've just mixed up two different questions: where can a name be seen, and how long does the data live. They're not the same."

J

Scope is about who can see a name. Lifetime is about how long the thing behind it exists.

John

Where a Name Can Be Seen vs. How Long the Data Lives

Two ideas, one word

People say "the variable is gone" — but the name and the data behind it can have different lives.

Functions can carry data

A function created inside another function can keep that function's data alive.

A process has a layout

Every running program divides its memory into the same four sections.

Lifetime, Scope and How a Process Uses Memory

The hotel guest analogy: think of a guest staying at a hotel. Scope is who can see the guest's name — say, only staff on the third floor can see the name card on the door. Lifetime is how long the guest actually stays in the hotel. These are different: a guest can stay for a week even though only the third-floor staff can see their name card.

In code, scope (Act 07) is where in the program a variable's name can be used. Lifetime is how long the data it refers to exists in memory. For a simple local number, they match: it's visible inside the function and it disappears when the function ends. But for data in the heap, lifetime is decided by reachability (last chapter), not by scope.

  • Closures — a function that packs a suitcase: when you create a function inside another function, the inner function "packs a suitcase" with any outer variables it uses, and takes it along. This is called a closure. The timer's little function () => releaseSeat(seatId) packed seatId in its suitcase. Even after holdSeat ends and its tray is gone, the suitcase lives on in the heap, together with the inner function, for as long as the inner function itself is reachable.
  • Why closures matter for leaks: a closure keeps everything in its suitcase alive. If a long-lived structure — like the timers map — keeps holding the timer, it keeps the timer's function, and the function keeps its suitcase. A small closure is harmless. A closure that packed a large object, kept forever, is a leak.
Table — Scope vs. lifetime
FeatureScopeLifetime
Question it answersWhere can this name be used?How long does the data exist?
Hotel versionWho can see the guest's name cardHow long the guest stays
Decided byWhere the variable is written in the codeStack: until the function returns; heap: while reachable
ExampleseatId is visible only inside holdSeatseatId lives on inside the timer's closure
Table — The leak, layer by layer
ThingLives inKept alive by
timers mapCreated at startup, lives all dayAlways reachable (a global)
Each timerHeapThe timers map
Each timer's functionHeapThe timer
Its suitcase (seatId, and more)HeapThe closure
Result300,000 holds a day, never removedMemory climbs until the 3 AM crash

The four sections of a process's memory

Stack

function call trays — grows downwards

↓

Free space

room for the stack and heap to grow

↑

Heap

objects, arrays, closures — grows upwards

Data section

global and static variables, live all the time

Code (text) section

the program's instructions — read-only

A closure packing a suitcase
function makeGreeter(name) {
// the inner function uses `name` — it packs it in its suitcase
return () => console.log("Hello, " + name);
}
const greetAnna = makeGreeter("Anna");
// makeGreeter has finished; its stack tray is gone...
greetAnna(); // ...but this still prints "Hello, Anna" — the closure kept `name` alive

The timer in holdSeat works exactly the same way: its function keeps seatId alive for as long as the timer is reachable.

How a process uses memory — four sections: when the operating system starts a program as a process (Act 04 and Act 05), it gives it its own virtual address space and divides it into four main sections. Think of a building with four floors, each with a job.

The code section (also called the text section) — the program's instructions, the recipe itself. Read-only, so the program can't accidentally change its own code. The data section — global and static variables that exist for the program's whole life, created at the start and kept until the end, like the timers map. The stack — the pile of trays for function calls, usually growing from the top of the address space downwards. The heap — the warehouse for dynamically allocated objects, usually growing upwards. The free space between the stack and the heap gives both room to grow.

Now the whole picture of the leak fits on one page. The timers map lives for the process's entire life (data section or heap, always reachable). Each hold adds a timer to it. Each timer holds a closure. Each closure holds its suitcase. Nothing is ever removed from the map — even after the seat is paid for or released. So every hold since the last restart is still in the heap. The memory graph climbs all day, and at 3 AM, when the nightly sales report runs and needs a burst of extra memory, the heap hits its limit and the process crashes.

Key Takeaway

Scope is where a name can be seen; lifetime is how long the data exists. Heap data lives as long as it's reachable, so a closure — a function that packs a suitcase of outer variables — can keep data alive long after the outer function ended. A process's memory has four sections: code (instructions), data (globals), stack (function calls) and heap (dynamic objects).

Why This Matters

Mixing up scope and lifetime is behind some of the most confusing bugs in modern code — data that should be gone but isn't, or closures that quietly hold on to huge objects. And the four-section picture of a process explains error messages you'll meet for years: stack overflow, heap out of memory, segmentation fault. It's the map Anna needed to see the whole leak at once.

Anna can now explain the 3 AM crash from top to bottom. Time to fix it — and to learn the other classic memory bugs, so she can recognise them on sight.

Next