Localhost vs production: why your app works on your machine but breaks online
In one sentence:Localhost is your app running privately on your own machine; production is the live version everyone else can actually use, and the two don't always behave the same.
What it actually is
Localhost is your computer talking to itself. When your AI agent runs your app “on localhost,” it starts a small web server on your own machine and you view it at an address like http://localhost:3000. Nobody else on the internet can reach it, only you, on that machine, right now. Production is the opposite: the real, published version of your app, running on someone else’s server (Vercel, Railway, a VPS, whatever you deployed to), reachable by anyone with the URL, all the time, whether your laptop is open or not.
Think of it like cooking at home versus running a restaurant. Localhost is your kitchen: you can burn the sauce, leave dishes in the sink, and nobody’s affected but you. Production is the restaurant: real customers are ordering, the kitchen has to actually work every time, and the ingredients (environment variables, databases, API keys) have to be stocked and paid for, not just sitting in your fridge.
Why your AI just did this
When you ask your agent to “show me the change,” it usually runs a command like npm run dev, which starts a local development server and gives you a localhost link to click. This is deliberate: it lets you and the agent see the app instantly, without waiting on a deploy, and without exposing half-finished code to the internet.
When you say “ship it” or “deploy this,” the agent switches modes: it builds an optimized version of your app and pushes it to a hosting provider, which assigns it a real, public URL. That’s production. Agents distinguish the two because code that runs fine locally often needs different settings once it’s live: a different database, real API keys instead of test ones, and a domain name instead of localhost.
When you’ll run into it
You’ll see it the moment you run npm run dev and a terminal prints something like “ready on http://localhost:3000.” That’s the local server starting up. You’ll see the other side right after a deploy: the app that worked perfectly a minute ago now shows a blank screen, a 500 error, or “Internal Server Error” on your live URL, while localhost still runs fine.
Classic causes: an environment variable you set in a local .env file but never added to your hosting provider’s dashboard, a database connection string that only allows requests from your home IP, or code that hardcodes localhost:3000 into an API call instead of using a variable that adapts to wherever the app is running. You’ll also hit this when a feature that worked in your browser fails for a friend testing the live link. That’s them hitting production while you were only ever testing localhost.
What to check
- Every environment variable in your local
.envfile is also set in your hosting provider’s dashboard (Vercel, Netlify, Railway) for the production environment - No code hardcodes
localhostor a local port. API calls and redirect URLs should read from an environment variable that changes per environment - You’ve tested a production build locally before deploying, not just the dev server (a production build can catch errors the dev server silently ignores)
- Your database accepts connections from wherever it’s actually deployed. If you’re on a serverless host like Vercel or Netlify, outbound IPs are often dynamic, so a database’s connection pooler (Supabase, Neon) usually works better than a fixed IP allowlist
- You’ve checked your hosting provider’s deployment logs for the actual error message, rather than guessing from a blank page
Say it like a dev
Instead of: “it’s broken” Say: “it works on localhost but throws a 500 error in production. Can you check if an environment variable is missing there?”
Instead of: “make it live” Say: “deploy this to production and confirm the production URL actually loads”
Instead of: “why does login not work on the real site” Say: “check whether the API URL is hardcoded to localhost instead of reading from an environment variable”
People actually ask
“what does npm run dev even mean”
It's the command that starts your app's local development server, the one that only runs on your own machine at an address like localhost:3000. It's for testing while you build. Nothing gets published or shared with anyone else just by running it.
“why does my app work on localhost but break once deployed”
Almost always it's a difference between the two environments: a missing environment variable, a hardcoded localhost URL, or a database/API that only accepts connections from your home network. Your hosting provider's deployment logs usually name the exact missing piece.
“how do I know if I'm looking at localhost or production”
Check the address bar: if it says localhost or 127.0.0.1, you're local; if it's a real domain or something like your-app.vercel.app, you're looking at production. When in doubt, just ask your agent which one it deployed to.
Related terms
Go deeper
Just met this in a real session? Glim reads it in plain words.
Paste what your agent just did, a git diff, your terminal, or its summary, and Glim tells you what changed and what to check before you ship. Nothing stored.
Explain my session →