Why does my app work locally but not after deployment?
Your laptop and your deployment are different environments. The usual culprits are environment variables that exist in one place only, URLs still pointing at localhost, a stricter production build, case-sensitive file systems, and real users hitting access rules you never triggered as the owner.
The problem
The feature works perfectly in development. The same commit, deployed, fails — sometimes at build time, more often at the first real interaction.
What it means
The code is probably fine. Something around the code differs: configuration, the machine it builds on, the data it meets, or the person using it. That is why reading the source repeatedly rarely helps here.
Common causes
| Cause | Typical symptom |
|---|---|
| Missing environment variable | 401, 500, or an empty feature |
| URL hardcoded to localhost | Login redirects nowhere, callbacks fail |
| Stricter production build | Deployment fails on type errors |
| Case-sensitive file system | Module not found for a file that exists |
| Stale dependency locally | Build fails only on the clean container |
| Access rules | Empty lists for everyone except you |
| Different database | Missing tables or missing data |
How to diagnose it
- 1Did the build succeed? If not, read the build log — the answer is in it verbatim.
- 2If the build succeeded, open the live site in a private window and reproduce the failure.
- 3Read the failing request's status and body in the Network tab.
- 4For a 500, open the function logs for that deployment.
- 5Compare the environment variable names in your local file against the hosting configuration, one by one.
How to fix it
- Add the missing variables to the production environment and redeploy — most changes only take effect on the next deployment.
- Replace hardcoded URLs with the request's own origin.
- Fix type errors rather than disabling the check that caught them.
- Rename files so the import matches exactly, including capitalisation.
- Run the production build locally once to reproduce the strict environment before deploying again.
What AI may have done
- Used `http://localhost:8080` for a redirect or callback URL because that is what worked while building.
- Added a new secret to your local file and mentioned production only in passing.
- Relied on a package installed for an earlier experiment and since removed from the lockfile.
- Tested by looking at the preview as the owner, where access rules never say no.
How to verify the fix
- 1Redeploy and confirm the new deployment is the one your domain serves.
- 2Walk the main flow on the live URL in a private window.
- 3Do it again signed in as a second account.
- 4Check the function logs for errors during that walkthrough, not just the visible result.
How to prevent it
- Keep a checked-in list of required variable names, with no values, so nothing is silently missing.
- Use preview deployments to test changes in a production-like environment before your domain sees them.
- Test as a second account routinely, not just before launch.
- Derive URLs from the environment rather than writing them down.
Frequently asked questions
- Why does my build pass locally but fail on deploy?
- The deployment builds from your repository in a clean container. Anything local — an installed package, an uncommitted file, a looser type check — is not there.
- Do I need to redeploy after changing a variable?
- Yes. Values are read at start-up, and browser-visible ones are baked in at build time.
- Can I copy my local environment file into production?
- Copy the names, review the values. Test keys and localhost URLs do not belong in production.
Practice this in MessyDev
Reading it once helps. Doing it once sticks. These are the hands-on parts of MessyDev that cover the same ground.
Keep going
- Environment variables explained for beginnersWhat an environment variable is, why the same code behaves differently in two places, which ones reach the browser, and how to check whether yours is actually set.
- What happens when you deploy an app to Vercel?From commit to live URL: install, build, output, edge and server functions, environment variables and why the production build is stricter than your laptop.
- Why isn't my environment variable working?The variable is set and the code still reads undefined. The six reasons that happens, in the order worth checking them.