Mon, November 3, 20252 min read

How a Nix flake made our polyglot stack (and new dev onboarding) fast and sane

JO
Johanan OttensooserProduct
LF
Lucio FrancoSenior Product Engineer

TL;DR

  • We had a README full of brew and apt-get commands. It was brittle and frustrating. On his first day, Lucio (a new hire) felt that frustration and built a Nix flake instead.
  • Other engineers started using it the next day: onboarding went from 30 minutes to 5, and new devs had a much better first-day experience.

Links: MooseStack repo | MooseStack Nix Flake | NixOS flakes docs

We used to onboard engineers with a README full of brew, apt-get, and curl commands. It was brittle, and a touch frustrating. On his first day, a new dev to our company, Lucio, built a Nix flake to replace that manual set up process.

By the end of that week, a bunch of our developers had adopted it. Setup time dropped from thirty minutes to five, and the onboarding pain dropped just as much.

Readme

Loading...

After: Nix flake

Lucio introduced a single flake.nix file to replace this README and its manual process. The core of the solution is the devShells.default output, which declaratively defines the complete toolchain.

Loading...

This file defines all dependencies, from language runtimes down to C libraries like rdkafka and openssl, in one place.

Adoption

The flake.nix PR on a Monday. On Tuesday, another dev from our team, Dave, onboarded. The entire process was git clone and nix develop. He had a fully functional, correct environment in under five minutes (mostly download time) versus the previous 30+ minute manual setup.

This rapid adoption wasn't just about the initial setup; it was a direct result of the technical guarantees.

1. A Standard Interface: The command is nix develop. No more setup guides or per-project instructions. If you use nix-direnv, it’ll even drop you into the dev shell automatically when you enter the project folder.

2. Atomic Pinning via flake.lock: The flake.lock file is the critical component. It's not just a package-lock.json or a Cargo.lock. It cryptographically pins the exact revisions of nixpkgs, rust-overlay, and all other inputs.

Loading...

This means a developer six months from now will get the exact same rustc, node, and openssl versions, eliminating environment drift.

Crucially, this also means adjustments to the environment are reproducible. If we need to add pkg-config, we add it to buildInputs, and the updated flake.lock guarantees every other developer gets that exact change when they next run nix develop.

3. Composability: We didn't have to solve Rust tooling in Nix. We just imported a community-maintained solution. The inputs block acts as a package manager for our entire toolchain.

Loading...

Conclusion

Nix Flakes gave us a reproducible, composable dev environment and cut onboarding time dramatically. They’re not without cost. The syntax takes getting used to, and flakes are still evolving. But, the stability we gained in day-to-day work easily outweighed those bumps: the friction of onboarding and, just as importantly, maintaining complex dev environments was significantly reduced.

Try the same Nix flake we use to build MooseStack in the MooseStack repository.

Interested in learning more?

Sign up for our newsletter — we only send one when we have something actually worth saying.

Follow us

Related posts

All Blog Posts