After a Postman request's script finishes, how do its variable writes reach the rest of the run?
answer
- The script works on copies, not the run
- Each set is recorded, not applied
- A diff is replayed when the execution ends
- MutationTracker carries the changes back
- Only the trackContext scopes are replayed
basics
~20 sAs a tracked diff. The sandbox records each set and unset as a mutation, and when the script execution ends the runtime replays those mutations onto the run's own scopes - but only for globals, environment and collectionVariables.
solid answer
~40 sThe script never touches the run's state directly. It works on sandbox copies of the scopes, and each `set` or `unset` is recorded as a mutation on the scope it targeted. When the execution finishes, the runtime takes that recorded diff for the scopes it asked to track — its item command declares `trackContext: ['globals', 'environment', 'collectionVariables']` — and applies it to the run. Two things follow. Entries the script never touched are never clobbered, because a diff carries changes rather than a whole scope, so two scripts writing different keys do not fight. And a scope outside that list, such as the execution-local layer written by `pm.variables.set`, has no route out at all, which is exactly why it cannot chain a value forward.
code
javascript · 2 linespm.environment.set('orderId', pm.response.json().id);
pm.environment.unset('tempToken');go deeper
Be ready to say that a script's writes are collected by the runtime after the script ends, and that only globals, environment and collection variables are collected at all.
Explain the diff: each set and unset is recorded as a mutation and replayed onto the run's scopes, so untouched entries survive and deletions travel too.
Use the model to reason about failures - a transport error means the test script never ran and nothing was collected, which looks identical to a write that went to an untracked scope.
Frame the tradeoff: a per-execution sandbox with an explicit carry-back list is what keeps parallel and repeated runs from silently sharing state, at the cost of one rule everyone must learn.
## Scripts work on copies The first thing to get straight is that a Postman script is not editing the run. It executes in a sandbox that has been handed the run's variable scopes, and what it manipulates there are those handed-over copies. If the story stopped at that, nothing a script did would ever matter to any later request. So there is a second half: a **carry-back**, performed by the runtime once the script execution completes. The carry-back is not a wholesale copy of the sandbox's state over the run's. It is a replay of recorded changes. ## Mutations, then a replay Each scope in the sandbox records what was done to it. A `set` is recorded as a mutation; so is an `unset`. The result is a **`MutationTracker` diff** — an ordered account of what changed on that scope during this execution, rather than a picture of what the scope looked like at the end. When the script finishes, the runtime asks the sandbox for those diffs and replays them onto its own scopes. | | Whole-scope copy | Recorded diff (what actually happens) | |---|---|---| | Untouched key written by another script | lost | preserved | | A key the script removed | ambiguous | removed, because `unset` is recorded too | | Cost of the handover | the entire scope | only what changed | ## Only the tracked scopes are replayed The runtime does not collect from everything the sandbox exposes. Its item command names the scopes it wants back: - `globals` - `environment` - `collectionVariables` That list is what makes chaining possible, and its length is what makes one specific mistake fatal. The sandbox also has an execution-local layer, written through `pm.variables.set`. It records mutations exactly like the others, but nobody ever asks for them, so they are discarded with the execution and no later request can see the value. ## What the diff model buys you - **Scripts do not overwrite each other's unrelated work.** One request's script writing `orderId` and another writing `customerId` both land, because each replays only its own recorded changes. - **Deletion is a first-class change.** `pm.environment.unset('orderId')` is not the absence of a write; it is a recorded mutation, so cleaning up a chained value at the end of a flow actually reaches the run. - **Order within one script is preserved.** Two writes to the same key end at the later value, because the mutations replay in the order they were recorded. - **Nothing is visible early.** A write is not in the run's state at the moment `set` returns; it is in the run's state after the execution that made it completes. ## Where the writes come from in the lifecycle Both script events feed the same machinery, and the difference between them is only timing. A **pre-request** script's execution completes before the request is sent, so its writes are in the run's state in time for the request being built. A **test** script's execution completes after the response has arrived, so its writes are in place for whatever runs next. The mechanism is identical; what differs is which side of the send the replay lands on. One consequence is worth remembering when diagnosing. If a request fails at the transport level, its test script does not run, so nothing is collected from it. A chain that depends on that script's write is broken not because the carry-back failed but because there was never anything to carry. ## The mental model to carry into an interview Say it in one sentence and you will be right about almost every follow-up: **a script proposes changes, the runtime applies them, and it only applies changes to the scopes it declared it wanted.** From that single sentence you can derive why `pm.variables.set` cannot chain, why an untouched key survives another script's writes, why an `unset` is as durable as a `set`, and why a value appears to exist inside the script that wrote it long before it exists anywhere else.
- Why does it matter that the carry-back is a diff rather than a copy?Because scripts writing different keys in the same scope do not destroy each other's work. A copy would mean the last snapshot wins and any key that snapshot never saw disappears. Replaying only the recorded changes leaves every untouched entry exactly as the run had it, which is what makes several requests contribute to the same store safely.
- Does an `unset` in a script travel back the same way a `set` does?Yes. Removing a key is recorded as a mutation just like a write, so `pm.environment.unset('orderId')` is replayed onto the run's environment when the script execution finishes. That is what makes clearing a chained value at the end of a flow reliable rather than cosmetic, and why a leftover value is a missing unset rather than a runtime quirk.
saying these in an interview costs you the question
- Says the script edits the run's scopes directly as it executes
- Thinks the whole scope is shipped back and replaces the run's
- Believes an untouched key can be lost to another script's write
- Assumes a write reaches the run before the script has finished
- Treats the execution-local layer as just another tracked scope