The Hidden Logic of Nix: Why Packaging Becomes Powerful Only When Names Stop Mattering
Hatched by Yuri Marques
May 12, 2026
9 min read
2 views
67%
The real problem is not installing software, it is naming it
Most people think package management is about getting software onto a machine. That is only the surface problem. The deeper problem is this: how do you identify a thing well enough to use it, upgrade it, and remove it later without confusion?
That question sounds ordinary until you notice how much software friction comes from naming. You ask for a package by one kind of name, remove it with another, and upgrade it by a third. The system remembers some identifiers but not others. What should be a simple lifecycle becomes a trail of mismatched labels. A package manager, in practice, is not just a delivery mechanism. It is a system for deciding which names matter, when, and for whom.
Nix makes that tension visible. Its language is built around precise references and attribute paths, while its package operations expose a surprising asymmetry: you install by attribute, but you may uninstall by derivation name. Upgrade can be targeted to one package or applied broadly to everything. At first glance, this looks like a quirk of tooling. Look more closely, and it becomes a lesson in software identity.
The question underneath all of this is not, “How do I install subversion?” It is, “What kind of object is a package, really?”
The lifecycle of a package is a lesson in identity
In many systems, software is treated like a mutable object with a stable human name. You install subversion, upgrade subversion, uninstall subversion. The name is treated as the thing itself. But that convenience hides a conceptual shortcut: names are not the same as identities.
Nix separates those ideas more sharply than most systems. An attribute path is a way of pointing to a package in a collection, like a coordinate in a map. A derivation name is closer to the concrete artifact that was built. These two forms of identification are related, but they are not interchangeable. That matters because a package is not just a label, it is a result of a build process, with a specific version, hash, and dependency structure.
This distinction becomes obvious when you try to remove software. The system may not remember the exact attribute path you used to install it, so it asks for the derivation name instead. Why? Because the package manager is not just tracking your intention, it is tracking a realized build. That asymmetry is annoying if you expect the interface to be perfectly symmetrical, but it is revealing if you care about correctness.
Think of it like addressing a person. In one context, a nickname is enough. In another, you need a legal name because the bureaucracy cannot operate on affection or familiarity. The name that helps you initiate an action is not always the name that helps you reverse it. Nix encodes that difference in the design of its commands.
The most important thing a package manager can tell you is not where software came from, but what kind of thing it considers software to be.
That is why package management in Nix feels less like app shopping and more like maintaining a carefully indexed world. Every action assumes a model of identity. The commands are not just utilities, they are philosophical commitments.
Why upgrade is the hardest command to make honest
If install and uninstall are about entry and exit, upgrade is about continuity. It asks a deceptively difficult question: what does it mean for something to remain the same while changing?
A package upgrade can happen in two modes. You can upgrade a single package by specifying its attribute path, or you can upgrade everything that has newer versions available. On the surface, this seems like a simple convenience feature. In reality, it reveals two competing views of software life.
The first view is local change. A package is upgraded because you decided that one component should move forward. The second is global drift. Your system is continually being pulled toward the newest available versions, whether or not you explicitly named each one. The package manager becomes a mediator between deliberate control and ambient freshness.
This tension mirrors a broader software truth: change is easy to request and hard to contain. If you upgrade a single dependency, you might stabilize one part of your environment while subtly reshaping another. If you upgrade everything, you gain uniformity at the cost of surprise. The beauty of Nix is that it makes this tradeoff explicit rather than pretending it does not exist.
The language component matters here too. Nix language primitives encourage exactness. You describe things as values, paths, attributes, and expressions, not as vague wishes. That exactness is not accidental. A package system that promises reproducibility must make identity and change legible at the same time. Otherwise upgrade becomes a semantic blur, a ritual of hope rather than a controlled transformation.
A useful mental model here is the difference between a map and a weather system. Install is like placing a marker on the map. Uninstall is removing the marker. Upgrade is weather, because it changes the terrain under the marker while you are still trying to stand on it. Nix’s command design acknowledges that upgrade is not merely another form of install. It is the command where identity and time collide.
The power of Nix is not control, it is recoverability
It is tempting to read Nix as a story about total control. The language is precise, the package references are structured, the commands are explicit. But that is only half the story. The deeper promise is not control, it is recoverability.
A system that distinguishes attribute paths from derivation names is not just being pedantic. It is preserving enough information to let you find your way back. That matters because software environments are not static. They are constantly accumulating history. Each install is a decision, each upgrade is a branch, each uninstall is a correction. The real challenge is not preventing all change, because that is impossible. The challenge is making change reversible in a meaningful way.
This is where the Nix language and package management model meet. The language gives you a way to describe a build precisely, and the package manager gives you a way to act on those descriptions while preserving traceability. Together, they reduce the gap between intent and artifact. That gap is where most system management pain lives.
Consider a simple analogy: a recipe versus a meal. A recipe is a description, a meal is an outcome. If you only store the meal, you can eat it once but you cannot recreate it. If you only store the recipe, you have a plan but no dinner. Nix treats packages more like meals that remain linked to their recipes. That connection is what allows you to upgrade without losing your bearings.
This is also why the uninstall behavior is so instructive. The system does not assume your memory is authoritative. It asks for the concrete thing that was actually installed. That may feel less friendly than a purely name based interface, but it is far more honest. Honesty is a feature when the thing you are managing is state.
A good package manager does not merely let you add software. It lets you answer the question, “What exactly did I add, and can I find it again?”
That shift in emphasis changes how you think about tooling. The best tools are not the ones that hide complexity most aggressively. They are the ones that preserve enough structure that complexity can be navigated later.
A mental model: three names for every thing
One way to understand the deeper design here is to think in terms of three layers of naming.
- Intent name: what you ask for when you want something, like an attribute path.
- Artifact name: what was actually built, like a derivation name.
- Policy name: what the system recognizes when deciding how to update or remove things.
Most software tools collapse these into one word and hope the differences stay invisible. Nix refuses to do that. Install operates on intent. Uninstall operates on artifact. Upgrade can act either locally or globally, depending on whether you are managing one object or your whole environment.
This three layer model explains why Nix feels strict but also coherent. The system is not trying to make all names equal. It is trying to keep the right name attached to the right job. That is a much harder and much more valuable goal.
Imagine a library. A patron asks for a book by title, the catalog records its call number, and the acquisition team tracks editions and print runs. If you used only the title everywhere, you would eventually misfile, misreplace, or misread the collection. Software packages have the same problem, just disguised by jargon. Nix handles the cataloging problem by being explicit about the different identities involved.
This is the hidden virtue of the package management model: it trains you to stop asking, “What is the package called?” and start asking, “Which identity is relevant to this operation?” That change in question is a leap in clarity.
Key Takeaways
- Separate intent from artifact. The name you use to request a package is not always the name you need to remove or audit it later.
- Treat upgrade as a semantic change, not a routine click. Upgrading one package and upgrading everything are different operations with different risk profiles.
- Prefer systems that preserve traceability. The ability to connect a build back to a concrete derivation is a form of recoverability, not bureaucracy.
- Use exactness as a tool for future clarity. Precise references may feel fussy in the moment, but they reduce confusion when environments evolve.
- Ask what kind of identity your tools assume. Many management problems come from tools that flatten different identities into one vague label.
The deeper lesson: software becomes manageable when it becomes legible
The strongest insight in this intersection is not about Nix specifically. It is about what makes any software environment manageable at scale. A system becomes tractable when its identities are legible, when you can tell the difference between a wish, a build, and a policy decision.
Nix language basics and Nix package management are connected by that same principle. The language gives structure to what you describe, and the package commands preserve structure in what you do. Together, they replace the illusion of simplicity with a more durable kind of simplicity: one built on explicit relationships.
That is why the package manager’s asymmetries matter. They are not flaws to be sanded down. They are reminders that the world of software is not flat. A thing can have more than one name, more than one identity, and more than one valid way of being addressed. The mature response is not to pretend those differences away. It is to design systems that respect them.
So the next time you see a command like install, uninstall, or upgrade, do not just think about action. Think about identity. Ask which name the system wants, which state it preserves, and what kind of truth it is trying to keep intact. In that sense, Nix is not just a package manager. It is a discipline for telling software the truth about itself.
Sources
Hatch New Ideas with Glasp AI 🐣
Glasp AI allows you to hatch new ideas based on your curated content. Let's curate and create with Glasp AI :)
Start Hatching 🐣