Nix
A domain-specific, purely functional, lazily evaluated language created by Eelco Dolstra to describe reproducible software builds and system configurations.
Created by Eelco Dolstra
Nix is a domain-specific programming language built for a single, ambitious purpose: describing how software is built, configured, and deployed in a way that is reproducible and declarative. Created by Eelco Dolstra beginning in 2003, the Nix language is purely functional, lazily evaluated, and dynamically typed. Rather than being a general-purpose language, it serves as the configuration layer for the Nix package manager and the NixOS Linux distribution, where every package and every system is expressed as a value computed by a Nix expression.
The central idea is striking in its simplicity: treat building software like evaluating a pure function. Given the same inputs — source code, dependencies, and build instructions — a Nix expression always produces the same output, isolated from the messy, mutable state of a typical operating system. This is the language’s reason for being, and it shapes every design decision within it.
History & Origins
Nix began in 2003 as a research project by Eelco Dolstra at Utrecht University, supervised by Eelco Visser. The earliest release is dated June 15, 2003. Dolstra was investigating a long-standing problem in software deployment — the unpredictability of installing, upgrading, and removing packages on conventional systems, often described as “dependency hell.”
The conceptual breakthrough was an analogy between package management and memory management. In a 2004 paper, “Imposing a Memory Management Discipline on Software Deployment,” Dolstra argued that the file system could be treated much like the heap of a running program, with packages stored at unique, content-addressed paths so that different versions could coexist without interfering. These ideas were developed in full in his 2006 doctoral thesis, “The Purely Functional Software Deployment Model.”
Around the same time, the first NixOS prototype was built by Armijn Hemel as part of his master’s thesis — a complete Linux distribution whose entire configuration is itself a Nix expression. The approach was presented to the wider research community in “NixOS: A Purely Functional Linux Distribution” at the ICFP 2008 conference, cementing the language as the foundation of a reproducible operating system.
Design Philosophy
The Nix language exists to make builds deterministic and side-effect-free, and its design follows directly from that goal:
- Purely functional. Nix expressions have no mutable state and no side effects during evaluation. A function given the same arguments always returns the same result, which is what makes builds reproducible.
- Lazy evaluation. Expressions are only evaluated when their values are actually needed. This matters enormously in Nix: a single expression may describe tens of thousands of packages, but only the ones you ask for are ever computed or built. Laziness lets enormous package sets be passed around cheaply without triggering expensive work.
- Declarative configuration. Instead of writing imperative install scripts, you declare what you want the result to be — a package, a development environment, an entire machine — and let Nix figure out how to realize it.
- Reproducibility through isolation. Builds run in isolation, with dependencies referenced by cryptographic hashes of their inputs, so results don’t depend on whatever happens to be installed on the host.
The language itself is deliberately small. It is dynamically typed with a handful of core types — integers, floats, strings, paths, booleans, lists, attribute sets (key/value maps), and functions — and its syntax is geared toward composing these into large, structured configuration values.
Key Features
- Attribute sets and functions. The attribute set (
{ key = value; }) is the workhorse data structure, and functions use a concisearg: bodyform, including pattern-matching over sets ({ a, b }: ...) that underpins how packages declare their dependencies. - Derivations. The fundamental build primitive is the derivation: a precise description of how to produce a build output from inputs. Every package in Nix ultimately reduces to derivations.
- The Nix store. Build results live in
/nix/storeat paths derived from a hash of all their inputs, so different versions and variants never collide and can be shared safely. - Lazy, infinite-friendly evaluation. Because evaluation is lazy, large package collections like Nixpkgs can be expressed as one big value without paying to compute parts you never use.
- String interpolation and paths. First-class path values and
${...}interpolation make it natural to weave file references and computed strings into build descriptions. - Flakes (experimental). Introduced with Nix 2.4 in 2021, flakes add a standardized, version-pinned way to package and compose Nix projects, improving reproducibility of the inputs themselves.
A minimal expression simply evaluates to a value — here, a greeting string:
| |
A slightly richer example shows attribute sets, functions, and laziness working together:
| |
Evolution
For its first decade, Nix matured as a research-driven open-source project, gradually accumulating the Nixpkgs package collection and refining the language and build model. A major inflection point came with Nix 2.0 in February 2018, a substantial overhaul that introduced the unified nix command-line interface and many ergonomic improvements, signaling a push toward broader, more practical adoption.
The next leap was Nix 2.4, released on November 1, 2021, which shipped the experimental flakes feature and the new CLI. Flakes addressed one of the model’s remaining weak points — the reproducibility of a project’s inputs — by giving Nix projects a standard structure and a lockfile that pins exact dependency versions. Flakes remained experimental but were widely adopted by the community.
In parallel, a commercial and tooling ecosystem grew up around the language. Determinate Systems, co-founded by Eelco Dolstra, produced a fast and reliable installer and its own Determinate Nix distribution, while consultancies such as Tweag became major contributors. By 2025, Nixpkgs had grown past roughly 120,000 packages, frequently cited as one of the largest and freshest software repositories of any package manager.
Current Relevance
Nix occupies a distinctive niche at the intersection of package management, build systems, and infrastructure-as-code. Its appeal has grown alongside industry interest in reproducible builds, supply-chain security, and declarative infrastructure — all areas where Nix’s content-addressed, purely functional model is a natural fit.
Today the language powers reproducible development environments (used by platforms such as Replit and Google’s Firebase Studio), scientific computing pipelines (CERN’s LHCb experiment), and the NixOS operating system, where an entire machine is defined by a single declarative configuration. The community is large and active, organized around Nixpkgs, the NixOS distribution, and a growing set of tools and conferences.
Nix is also known for a steep learning curve: its purely functional, lazily evaluated semantics and its highly domain-specific vocabulary can be challenging for newcomers. But for teams that need builds and environments to be exactly reproducible, the investment often pays off in reliability that imperative tooling struggles to match.
Why It Matters
Nix demonstrated that ideas from functional programming — purity, laziness, immutability — could be applied not just to computing values in a program, but to the very act of building and deploying software. By modeling deployment as the evaluation of pure functions over hashed inputs, it offered a principled answer to dependency conflicts, “works on my machine” failures, and irreproducible builds.
That insight has rippled outward. The package manager GNU Guix adopted the same functional deployment model (expressing it in Scheme rather than the Nix language), and configuration languages such as Dhall drew on Nix’s approach to typed, programmable configuration. Whether or not developers use Nix directly, its core lesson — that reproducibility is achievable when you treat builds as pure functions of their inputs — has become an enduring contribution to how the industry thinks about software deployment.
Sources include the Nix and NixOS research page, Eelco Dolstra’s NixOS ICFP 2008 paper, the Nix 2.0 release announcement, and the Wikipedia article on Nix.
Timeline
Notable Uses & Legacy
CERN — LHCb experiment
CERN's LHCb collaboration has used Nix to package and reproducibly build scientific software, helping ensure that analysis environments can be recreated exactly across machines and over time.
Replit
The online development platform Replit adopted Nix to define reproducible per-project development environments, letting users declare system packages and toolchains declaratively.
Google Firebase Studio
Google's Firebase Studio (formerly Project IDX) uses Nix to define and provision cloud workspace environments, so each project's tooling is described declaratively and reproducibly.
Determinate Systems
Determinate Systems, co-founded by Nix creator Eelco Dolstra, builds tooling and enterprise support around Nix — including a widely used installer and the Determinate Nix distribution.
Tweag
The software consultancy Tweag has been a major contributor to the Nix ecosystem, using and extending Nix for reproducible builds and continuous integration across client projects.
Language Influence
Influenced By
Influenced
Running Today
Run examples using the official Docker image:
docker pull nixos/nixExample usage:
docker run --rm nixos/nix nix-instantiate --eval --expr '"Hello, World!"'