Understanding nix channel updates

Hi, whenever I add a new channel, like upgrading from 25.11 to 26.05, and then running
nixos-rebuild dry-build --upgrade, the update is huge. There are dozens or even hundreds of derivations being updated. Often the required disk space extends 15GB.

I noticed that many derivations are not even new versions. emacs was version 30.2 in 25.11 and is 30.2 in 26.05 still. However, the store paths are updated and gigabytes of space are required.

Can someone explain this to me? And are there workarounds? My / partition is 49GB and I don’t think I use lots of programs, still these channel updates are always a hassle. To complete the last, I collected garbage and optimized the store while doing the rebuild. I thought everything will break, but thankfully it worked.

If a dependency changes, than the thing itself is different as well.

This is a general property of nix, and even it’s core idea.

1 Like

okay, so let’s say emacs depends on glibc and glibcis updated. Then, emacs is build using the new glibc version and thus, the store path changes.

Is there anything I can do to lessen the disk space requirements? I’m on a laptop with a rather small SSD so I do not have ton of space

Enable automatic store optimisation, reduce the system closure, GC regularly, get a bigger disk.

4 Likes

To some extent, this is just the price you pay for using nixos. It’s heavier on the disk space and network bandwidth requirements than most distros, because nix is so particular about whether things are exactly the same or not, and because we keep old generations around.

NobbZ covered the mitigation approaches available, though I would add that you can make GC automatic, so you don’t need to think about it.

1 Like

I second the recommendations for auto optimization and GC. Take a look at, for example, programs.nh.clean and services.angrr for more control over what gets pruned when.

Also, two other tools that are good for looking under the hood and getting a better idea of what’s taking how much space:

nh: Gives you a quick look at closure sizes so you can see how much a single system build is actually taking, and how much it’s changed lately. Comparing to the results from disk tools like df can be informative and tells you how much duplication you really have.

$ nh os info
NixOS 26.05.20260831.5dfba62
Generation No Build Date           NixOS Version          Kernel  Closure Size
270 (current) 2026-09-01 07:13:27  26.05.20260831.5dfba62 6.18.48 2.7 GB
269           2026-08-30 08:39:31  26.05.20260829.c5c4a43 6.18.48 2.7 GB
268           2026-08-28 10:36:11  26.05.20260827.d57af92 6.18.47 2.7 GB
267           2026-08-24 20:37:19  26.05.20260823.a3b9886 6.18.46 2.7 GB
266           2026-08-23 07:47:42  26.05.20260822.a9e6d84 6.18.45 2.7 GB

$ df -h
Filesystem      Size  Used Avail Use% Mounted on
/dev/vda2       128G  7.9G  117G   7% /
/dev/vda2       128G  7.9G  117G   7% /nix

Here I can see that my system build is 2.7G, and my five retained generations add up to 7.9G. Not bad. (This example is for a small server on a VPS. Desktop numbers will be bigger)

nix-tree: Lets you examine what depends on what within a single closure. After running it, do / emacs to search for your emacs package, see how big it is, and browse its dependencies. If you have something big in the store and don’t know why it’s there, this is a quick way to find out.

2 Likes

Another mitigation is to use a filesystem with support for compression. The nix store is very amenable to compression: on my store compress=zstd:3 halves disk usage

$  sudo compsize /nix/store
Processed 7144223 files, 1828983 regular extents (5179776 refs), 4112338 inline.
Type       Perc     Disk Usage   Uncompressed Referenced  
TOTAL       49%       89G         180G         423G       
none       100%       48G          48G         116G       
zstd        30%       40G         131G         306G       
prealloc   100%      8.7M         8.7M         175M  
3 Likes