← Writing

NODE_ENV=development on your build server silently breaks builds

Package managers change install behavior based on NODE_ENV — set it to development on a Coolify build and the build can fail in ways that look like missing dependencies.

While mirroring a production stack into an isolated dev environment on Coolify, I set NODE_ENV=development on the cloned services — it’s the dev environment, after all. Builds started failing.

The lesson: NODE_ENV is not a label, it changes package-manager and build-tool behavior. Depending on the value, installs decide whether devDependencies come along, and frameworks switch between dev and production code paths your build pipeline may never have been tested against. Flip the value in the wrong place and the failure surfaces later as some tool “not found” or a build behaving unlike production — nothing points back at the env var you changed.

The deeper trap is that NODE_ENV is overloaded: frameworks read it to pick dev/prod behavior, package managers read it to decide what to install, and build servers pass it to both stages. One variable, three meanings.

What I do now on Coolify:

  • Keep NODE_ENV out of build-time variables entirely, or pin it to production for the build and let the install step explicitly include dev dependencies if the build needs them.
  • Express “this is the dev environment” through my own variables (APP_ENV, feature flags, distinct API URLs), never by repurposing NODE_ENV.
  • When a cloned service builds differently from the original, diff the environment, not just the code — a clone that “kept” settings from the source service is carrying invisible state.
← All writing Book a call →
Book a call → WhatsApp