Why use flakes?

I am very new to Nix and NixOS and have recently been learning about nix flakes. They seem to guarantee better reproducibility, but at what cost?

From what I understand, packages inside traditional package repos never make breaking API/ABI changes, such that one installed instance of that package can satisfy hundreds of packages that depend on it. When a breaking change is required, a new package is made instead of modifying the existing one (e.g.: openssl and openssl_3). This saves a lot of disk space, and it seems nixpkgs also follows this principle.

However, flakes lock their own instances of nixpkgs, duplicating otherwise ABI-compatible packages and therefore wasting disk space. This leads to a very frequently discussed situation - 1000 instances of nixpkgs. However, forcing flakes to use a common version of nixpkgs to fix the space issues seems to defeat the purpose of flakes, so I ask - why use flakes?

Forced pure eval and consistent API for consumers.

But the downside is much longer eval times and disk space usage.The design is also not well-thought-through.

Aside: at least with flakes you can override the nixpkgs (or any) input quite easily.
Without flakes you might have more trouble.

4 Likes

“Flakes” are a big conglomerate of different features that all have different purposes (which in turn is one of the biggest issues with this, and why it’s still experimental like 7 years later). You seem to mostly be concerned with input pinning here. Input pinning is mainly useful if you use nix for software builds.

The feature does have the downsides you mention, but there’s a reason pretty much every code ecosystem has facilities for pinning dependencies these days. ABI compatibility is useful from a system deployment point of view, since being able to swap out versions of a library means nice things for security and disk space, but when developing software you don’t really care about that - here you only care that you have consistent behavior so that you can reason about what your software does; nix as a tool is all about ensuring this consistency.

This argument actually goes all the way back to the 80s/90s, funnily enough - back then it was about whether you should dynamically or statically link your dependencies. Nix, docker, flatpak & co. are the eventual answer to the dynamic linking folks winning that initial argument in the unix world, since that lead to issues for developers, especially as reliance on third party code dependencies has completely exploded (in the dos world the static linking folks won, and .exe files are still universally bloated to this day!).

So, input pinning is not very useful from a NixOS user’s perspective, and can indeed be argued to be a downside, but from a developer-using-nix perspective input pinning is absolutely essential. Without it nix doesn’t solve the “builds on my machine” problem it’s supposed to solve at all.

The feature isn’t very well thought-out, unfortunately, precisely because it lacks facilities for advertising ABI compatibility. You could easily pin inputs intelligently, ensuring that your input tree respects ABI compatibility - like e.g. rust’s cargo does. Detsys have a proprietary solution to this problem, which, well, let’s just say their championing of this flawed design, and later insistence on marketing flakes as “done” has left a bad taste in the community’s mouth.

Flakes also aren’t the only (nor the first) implementation of this in nix land. I’d argue niv is much less intrusive. Nix should have built-in functionality for input pinning, it’s a shame that the current design is lacking and that it comes with all this other baggage.


So bottom line, why pin your inputs with flakes? Because that’s very useful for software development. The feature is also currently flawed and really needs work.

6 Likes

For those with less mastery of the nix language, the forced pure eval can also be a significant advantage. People without a clear idea of the process of nix language evaluation and how eval time, build time, activation time, and run time all link together can easily write nix code that’s not at all reproducible. Flakes give you guardrails to prevent those kinds of mistakes. But at a non-trivial cost in eval time due to copying to the nix store.

TLATER already covered the input pinning issue quite well so I won’t say more on that.

2 Likes

Tbh nix could just have a lint for this. It’s utterly insane to go to this extent just to have a guardrail for newbies. Any meaningful inconsistency of file paths caused by repo location is solved by the build sandbox already.

… but that’s besides the point, yeah, this is another part of the flake umbrella.

4 Likes