Beta
Start your first lab →
BlogManifestoContactStart your first lab →
❮ Blog · Nix · NixOS · Engineering
August 27, 2026 — 3 min read

Why does shipping a Nix upgrade move only the difference?

Closures, the third Part of LabCraft's Nix course, is now available. On a real NixOS machine, it asks you to predict what an upgrade will actually move before Nix shows you the answer.

You want to run a tool on another machine, so you copy its store path across with cp. What lands is rubble. The files are there, but every reference inside them points at /nix/store/<hash> entries that don't exist on the far side, and nothing there knows the path is even registered.

A store path never travels alone. The unit that actually runs is its closure: the path plus everything it transitively needs. And once you move closures instead of files, a surprising thing happens — shipping an upgrade to a target store that already has the old version can cost only the difference between them.

That is the part the lab makes you prove. The old and new closures may share more than your filesystem instincts expect, and Nix can tell what the target store already has before it moves anything.

Closures is the new free Part of LabCraft's Nix course, built on exactly that surprise. It isn't a lecture about graph theory; it's a set of labs where your normal filesystem instincts stop working and the machine makes you account for what's actually there.

The directory is not the thing

Most of us learn to ask filesystem questions first. How big is this directory? What changed between these two trees? Can I copy this path to another machine?

Those are reasonable Unix questions. They are also too small for Nix. A Nix store path carries references to other store paths, and the useful unit is the whole reachable graph. A directory can look small while the thing that runs is large. Two versions can look different while most of their closures are shared. A copied path can look complete and still fail because the rest of its graph did not come with it.

The lab keeps the answer just out of reach

Closures does not ask you to memorize another command. It asks you to build judgment around four operational questions:

  • What does a tool actually cost: its own bytes, or everything it needs to run?
  • When a closure is heavier than expected, which member made it heavy?
  • When one runtime becomes another, what changed and what stayed shared?
  • If the target already has the old version, how much of the upgrade actually travels?

Those are the questions behind binary caches, deploy targets, images, and garbage-collection roots. They are also the questions that are hard to learn from prose alone, because the wrong answer can sound perfectly plausible until you watch the store prove otherwise.

Why this became Part 3

Store Paths taught you to name a store path and list its closure with one command. That's the noun. Closures is the verbs: size, weigh, diff, move. The closure stops being a list you can print and becomes the unit you budget disk for, ship between machines, and pull from a cache.

It runs on a real NixOS machine, because the running system is the largest, most honest closure a learner can inspect — kernel, init, every service, the shell, all real store paths with real references already on disk. You don't write a line of the Nix language. The first labs inspect closures that already exist on the machine; the later ones realize two Node runtimes, compare their closures, and copy the missing paths into a file store.

Start the Nix course. Predict what the copy will move before the machine shows you the delta.

Share this

Read next

Start your first lab.

LabCraft is open as a public beta. GitHub, Google, or a magic link to your inbox — pick your way in.

By continuing, you confirm that you are at least 18, agree to our Terms, and acknowledge our Privacy Policy.

LabCraft · Beta · 2026PrivacyTerms
labcraft.dev