Railway shipped its second auto-build engine replacement in thirteen months. First it dropped Heroku buildpacks for its own Nixpacks tool in February 2025. Then, on March 4, 2026, it put Nixpacks into maintenance mode and shipped Railpack — a full rewrite, different language, different underlying tech — as the new default. If you're building a self-hosted, git-push PaaS and you've been quietly embedding Nixpacks as the thing that turns a repo into a running container, that's not a changelog entry. It's a decision you now have to make yourself.
The Three Real Options, Compared
Here's the decision, upfront, scoped to what actually matters for a self-hosted git-push PaaS choosing (or embedding) an auto-build engine today — not Render, Fly.io, or GitHub Actions, whose build layers are a separate question, but the Heroku-buildpack lineage specifically:
| Nixpacks | Railpack | Cloud Native Buildpacks / Paketo | |
|---|---|---|---|
| Status (mid-2026) | Maintenance mode — no new features | Active, beta since March 2026 | Active, CNCF Incubation since Nov 2020 |
| Image size vs. Nixpacks | Baseline | 38% smaller (Node), 77% smaller (Python) | Comparable to Nixpacks; not optimized for minimal size |
| Governance | Single vendor (Railway) | Single vendor (Railway) | Multi-vendor (Heroku, Google, VMware/Broadcom-Paketo, Red Hat) |
| Build layer | Nix package manager, /nix/store | Custom BuildKit LLB frontend | pack CLI + Lifecycle spec, OCI-native |
| Contract age | ~2 years (2022–) | New (2026–) | 15 years (Heroku 2011 origin), formal spec since 2018 |
| Adopted by (self-hosted PaaS) | Coolify (default) | Coolify (beta option), Dokploy | Dokploy |
The 38%/77% figures are Railway's own benchmarks and cover Node and Python specifically — the two languages Railway's blog post measured, not a universal ratio across every runtime Railpack supports. If your fleet is mostly Go or Ruby services, treat those numbers as directional, not a guarantee.
Two things fall out of that table immediately. First, Nixpacks isn't going away tomorrow — "maintenance mode" means existing projects keep building, just with no forward investment — but it's now the tool you'd be building new infrastructure on top of by choice, not by default. Second, there's a third option in that table that most "Railpack replaces Nixpacks" coverage skips entirely: Cloud Native Buildpacks, the spec Heroku itself open-sourced and that's still under active, multi-vendor maintenance. The rest of this post works through why that table looks the way it does, and which row you should actually build on.
What Actually Changed Under the Hood
Nixpacks worked by shelling out to the Nix package manager: it inspects your repo, decides what Nix packages to install (Node, a specific Python version, system libraries), and materializes them into /nix/store before layering your app on top. That approach is powerful — Nix's package set is enormous and pins exact versions — but the /nix/store layout doesn't compress or dedupe well in a container image, and Railway's own numbers show it: Railway's blog describes a simple Node app producing an 800MB–1.3GB image through Nixpacks, versus 50–100MB from a hand-tuned Dockerfile. That gap is the entire reason Railpack exists.
Railpack throws out Nix entirely. Instead of generating a Dockerfile or shelling out to a package manager, it builds a JSON build plan describing each step's inputs and outputs, then compiles that plan directly into BuildKit's low-level intermediate format (LLB) through a custom frontend. BuildKit solves the resulting graph starting from the end and working backward, pulling from cache wherever it can and only re-running the steps whose inputs actually changed. That's a materially different caching model than Nixpacks' Nix-derivation caching — Railpack can hash the exact environment variables a build step reads and invalidate only that layer when they change, rather than invalidating a whole derivation.
The size numbers that fall out: a Node app that produced an 800MB–1.3GB image on Nixpacks comes in around 450MB on Railpack — Railway's own reported 38% reduction — using an Ubuntu base with standard package managers instead of the Nix store. Python fares better still, at a 77% reduction, since Python's Nix packaging carried unusually heavy runtime overhead.
The implementation detail that surprised a lot of Railway watchers: Railpack is written in Go, not Rust like Nixpacks. Railway's stated reason is pragmatic rather than ideological — BuildKit's own libraries are Go, and building a custom LLB frontend on top of them is a much shorter path in Go than reimplementing that integration surface in Rust.
Railway's own framing of the motivation, from its "Why We're Moving on From Nix" post, is a scale argument: Nixpacks worked for roughly 80% of its use cases, but at 200,000+ users, the remaining 20% was still a large absolute number of people hitting image-size and caching limits every day. Scaling toward its next order of magnitude of users meant a different foundation, not an incremental fix.
Self-Hosted Tools Caught Between Builders
This is where "Railway replaced an internal tool" turns into an actual decision for people who don't work at Railway. Nixpacks was never Railway-exclusive — it's MIT-licensed and open source, and several self-hosted PaaS projects embedded it as their own auto-build engine, on the reasonable bet that a well-funded platform company would keep investing in it. That bet just resolved:
- Coolify ships Nixpacks as its default auto-detect builder today, alongside Dockerfile and Docker Compose support. Railpack has landed as a newer, beta-status build option, but Nixpacks is still what a fresh Coolify install reaches for automatically.
- Dokploy already supports the broadest set: Railpack, Heroku buildpacks, Paketo buildpacks, and Dockerfiles, alongside Nixpacks. It's the one self-hosted tool in this comparison that isn't making a single-vendor bet at all — it's hedging across all four.
- Easypanel never adopted Nixpacks in the first place; it built on Heroku buildpacks from the start, which puts it closer to the Cloud Native Buildpacks lineage than the Railway one.
The practical risk for a project like Coolify isn't that Nixpacks stops working — maintenance mode means it keeps building your existing app definitions indefinitely. The risk is the same one Railway itself just demonstrated: a build tool with no forward investment eventually falls behind on new-runtime support, security patch cadence, and the caching/size characteristics that Railpack was built specifically to fix. If Coolify's roadmap doesn't already include a path off Nixpacks, this is the moment that path gets planned, not the moment it gets executed under pressure.
The Alternative Nobody's Marketing: Cloud Native Buildpacks / Paketo
The self-hosted-PaaS conversation around this migration has mostly framed it as "Nixpacks vs. Railpack" — a two-option question. It isn't. Cloud Native Buildpacks (CNB), the CNCF-Incubation spec that formalized Heroku's original 2011 detect/compile/release contract, has been under continuous, multi-vendor development the entire time Nixpacks existed, and it's still moving in 2026.
The governance difference is the whole story here. Nixpacks and Railpack are both single-vendor tools — Railway builds them, Railway decides when they get replaced, and Railway just proved it will replace one on a roughly 13-month cycle when its own scaling needs demand it. CNB is different by design: Heroku's own disclosure of its CNB maintenance work counts 27 releases shipped across CNB projects in a 14-month window, more than 65 community pull requests reviewed, with named contributors spanning Heroku, Google Cloud, Red Hat/OpenShift, and VMware Tanzu.
Paketo — the most complete open buildpack implementation of the CNB spec, now under Broadcom/VMware stewardship — keeps pace with language runtimes on its own schedule. Java 26 support landed within about a week of the JDK vendor release, even though Paketo's own default stays a version behind (Java 25 becomes the default in September 2026, at which point Java 26 gets dropped in favor of Java 27's imminent release). That's a maintenance cadence built to survive any single contributor pulling back — which is exactly the scenario Heroku itself is currently in, running in sustaining-engineering mode since February 2026 while still shipping CNB commits.
The tradeoff for that stability is real: CNB/Paketo images aren't optimized for minimal size the way Railpack is, and the pack build workflow carries more conceptual surface (buildpacks, builders, stacks, the Lifecycle binary) than Railpack's single build-plan abstraction. You're trading Railpack's raw efficiency for a spec that four different companies have independent business reasons to keep alive.
Which One Should a Git-Push PaaS Bet On
There's no single right answer here — it depends on what you're actually optimizing for, but the tradeoff is concrete enough to state as a rule:
- Bet on Railpack if minimal image size and build speed are the metric that matters most for your users, and you're comfortable with a single-vendor roadmap that has already changed direction once. Railway's own production traffic is a real forcing function keeping Railpack maintained, but nothing obligates Railway to keep it stable for the next self-hosted tool that embeds it, any more than Nixpacks was.
- Bet on Cloud Native Buildpacks/Paketo if you're building infrastructure other people will depend on for years and want a contract with 15 years of lineage and four independent maintainers, at the cost of somewhat larger images and a heavier CLI/spec surface.
- Bet on all of it, with a Dockerfile escape hatch, if you're building the platform layer itself rather than just choosing what to run on. Dokploy's approach — support Railpack, Nixpacks, Heroku buildpacks, and Paketo side by side, with Dockerfile always available as the fallback that never breaks — is the actual answer for anyone shipping a self-hosted PaaS product, because it converts "which vendor do I bet on" into "which vendor does this specific user's app want," decided per-deployment instead of once at architecture time.
That last option is the one worth sitting with. The entire reason Railway could swap Nixpacks for Railpack without breaking a single Railway customer's git push workflow is that the auto-build engine sits behind a stable interface — repo in, container out — and nothing about that interface required Nixpacks specifically. Any platform that keeps its build engine swappable behind the same interface inherits that same flexibility for free.
Bex.co is the open-source, AI-native Render alternative — push a git repo, get a running HTTPS service on machines you own. Its build step today is intentionally manual (you run docker build locally and import the image straight into the node), which means the Railpack-vs-Nixpacks-vs-CNB tradeoff covered here is still ahead of it on the roadmap, not behind it — worth knowing if you're picking an auto-build engine for your own git-push pipeline in the meantime. Star the repo on GitHub or deploy your first app today.