Build Engines
A build engine is what turns your source code into a runnable container image. Vessl supports three, and you can change which one an app uses at any time.
| Engine | Best for | Notes |
|---|---|---|
| Railpack | Most apps — auto-detected language stacks | Default for detected languages |
| Nixpacks | A mature, broad fallback | Battle-tested auto-builder |
| Dockerfile | Full control | Used automatically when a Dockerfile is present |
How Vessl chooses
When you import a repository, Vessl inspects it and pre-selects an engine:
Dockerfilepresent → Dockerfile (your Dockerfile always wins — see Dockerfile Builds).- A detected language (Laravel/PHP, Django/Python, Node.js, Go, …) → Railpack (the default).
- A static site → the static builder (see Static Sites).
- No clear signature → Nixpacks.
You can always override the pre-selected engine — nothing is forced.
Railpack (default)
Railpack is a modern builder (the successor to Nixpacks) that handles toolchains Nixpacks can't — for example Gradle 9 and current Java/Spring stacks. It's the default for newly detected language stacks.
Railpack is proven across PHP/Laravel, Python/Django, Node, and Go. Because every repository is different, a build that succeeds on one engine can occasionally fail on another — if a build looks engine-related rather than a problem in your code, switch engines and redeploy (see below).
Known limitations
- From-source runtimes. Railpack compiles some language runtimes (notably Ruby and Elixir/Erlang) from source on the first build. That first build can be slow or exceed the build budget for very large apps. Subsequent builds reuse the cached layer. (Go, Node, PHP, Java use prebuilt runtimes and are fast.)
- Gradle Java version. Railpack provisions JDK 21 and (on the pinned version) ignores a project's Gradle toolchain pin — a project requiring a different JDK may need the Dockerfile engine.
- Build-time environment. Add-on connection variables (e.g.
DATABASE_URL) are injected at runtime, not at build time. Apps that need a database during the build (e.g.prisma generate, some asset pipelines) should set the needed value explicitly as a build-time variable. - Overriding a Dockerfile repo. If you force Railpack on a repo that ships a
Dockerfile, Railpack ignores the Dockerfile (including itsENV/EXPOSE). Set the Target Port and any required env on the app instead — or just use the Dockerfile engine.
Nixpacks
Nixpacks is the original auto-builder — mature and broad. It remains fully supported and is the safest choice for unusual stacks. If a Railpack build fails for a reason that looks engine-related, Nixpacks is the first thing to try.
Dockerfile
If your repo has a Dockerfile, Vessl builds with it for full control over base image, system packages, and multi-stage builds. See Dockerfile Builds.
Switching the engine
You can change the engine without recreating the app:
- Open your app → Settings → Source & Build Pipeline.
- Under Build Engine, pick Nixpacks, Railpack, or Dockerfile.
- Save, then Redeploy — the new engine takes effect on the next deployment.
You can also choose the engine in the create wizard under Build & Config.
If a deployment fails and the cause looks like the builder rather than your code, switching engines and redeploying is the quickest thing to try. Existing apps keep whatever engine they were created with — changing the platform default only affects newly created apps.
See also: Troubleshooting Deploys.