DEV Community

pante5ter
pante5ter

Posted on

"It Works on My Machine" — Why Deploys Break and How to Stop It

The app runs perfectly on your laptop. You push to production and it white-screens, 500s, or won't even build. This is one of the most common — and most fixable — categories of bug. The cause is almost always a difference between your machine and the server.

1. Missing environment variables

Number one by a wide margin. Your local .env has the API keys and database URLs; production doesn't, because .env isn't committed (correctly). Locally the app finds its config; in production it gets undefined and crashes.

Fix: keep a committed .env.example listing every variable (names only, no secrets). Before deploying, confirm every variable in it is set in your host's dashboard. Most "works locally, breaks in prod" tickets end here.

2. Build-time vs runtime confusion

In frameworks like Next.js, some code runs at build time and some per request. A value that exists at runtime locally might be needed at build time in production — or a variable not exposed to the browser is read in client code and comes back empty.

Fix: know which code runs where. Public values the browser needs must be prefixed correctly (e.g. NEXT_PUBLIC_). Secrets must never be read in client components.

3. Case sensitivity

Your laptop (macOS, Windows) is usually case-insensitive: import Button from './button' finds Button.tsx. Production runs Linux, which is case-sensitive — and that import fails the build.

Fix: match the exact case of filenames in every import. A green local build and a red production build with "module not found" is almost always a case mismatch.

4. Dependency drift

Locally a package is cached at the version that worked. Production installs fresh from your lockfile — or without one, gets a newer, slightly different version.

Fix: commit your lockfile and make sure CI installs from it. "It built last week and not today, with no code change" is the signature of dependency drift.

5. Node version mismatch

You're on Node 20 locally; the host defaults to Node 18. A feature you rely on isn't there, and the build fails on something that looks unrelated.

Fix: pin the Node version in package.json (engines) and in your host's settings. Make the two match.

A deploy checklist that makes this boring

  1. Every variable in .env.example is set in production.
  2. The project builds from a clean clone, not just incrementally.
  3. Import paths match filenames exactly (case included).
  4. The lockfile is committed and used.
  5. Node versions match locally and in the host.

Fix the root cause once — usually env vars and case sensitivity — and "works on my machine" stops being a phrase you dread.


Got a build that runs locally but won't deploy? That's a same-day fix — I find the exact mismatch, get it green, and tell you what went wrong so it stays fixed. vengstudio.online.

Top comments (0)