apps/www/_blog/2024-04-25-nix-postgres.mdx
Straight from the Nix manual:
Nix is a purely functional package manager. This means that it treats packages like values in purely functional programming languages such as Haskell — they are built by functions that don’t have side-effects, and they never change after they have been built. Nix stores packages in the Nix store, usually the directory
/nix/store, where each package has its own unique sub-directory such as
/nix/store/b6gvzjyb2pg0kjfwrjmg1vfhh54ad73z-firefox-33.1/
where
b6gvzjyb2pg0…is a unique identifier for the package that captures all its dependencies (it’s a cryptographic hash of the package’s build dependency graph). This enables many powerful features.
The implications of purely functional builds are too far reaching to fully explore here, but the key properties we’re excited about are:
The main artifacts from the supabase/postgres build pipeline include:
We use popular tools like Packer and Ansible in tandem with GitHub Actions to build, test, and release those artifacts in CI.
Over time the Supabase Platform has grown up. We started with Postgres, PostgREST and Realtime. Next came Auth, and Storage, then GraphQL, and Functions. Postgres itself also has a suite of independently versioned extensions that we maintain and periodically upgrade.
As the constraints from the various tools in our stack combined it became impractical to run builds on local development machines. To accommodate, we pushed all builds to consistent build machines on CI. Today those builds take between 30-60 minutes. Given some of the larger components we bake in, like PL/v8, we’re fairly happy with that runtime. Even so, we can do better!
When first exploring Nix, we started with a prototype supabase/nix-postgres, which implemented the basics of our Postgres build with the majority of our supported extensions. Initial experiments showed that the nix cache significantly reduces our build times. The size of the reduction depends on how much of the cache is invalidated by the change being made. Broadly speaking, the cache reduces build times for common operations from roughly 40 minutes to between 1 and 5 minutes!
We have now added the nix build in parallel with our Ansible/Packer build in the main supabase/postgres repository and are steadily reducing the differences between the two. Using Nix (and Nix Flakes) we created a package set, which now lives at /nix and is coordinated with flake.nix.
We are currently working on integrating our Nix packaged assets into our AMI build in a way that will allow our teams to continue to use packer and ansible to build and configure AWS AMI images, but sources postgres from our Nix build. We think that integrated approach will make it simpler for Supabase to adopt and leverage Nix. We’ll increase our internal documentation and education on the Nix aspects of the build pipeline. We’ll also be in a great position to use Nix community tooling to scan for vulnerabilities, versions, etc and create automation around those issues.
The further we delve into the project, the more opportunities present themselves. Some of the planned features we’re excited about are:
Stay tuned for updates as we leverage the power of Nix to bring more robust and efficient solutions to our community!