Why Your AI-Generated App Works on Localhost but Breaks in Production
The most confusing bug in software is the one that only happens somewhere you can't see. Your AI-generated app is not working in production, it worked perfectly on localhost ten minutes ago, and the logs — if you can find them — say something unhelpful like ECONNREFUSED or Cannot find module. The good news: AI-built apps fail in production in a small number of predictable ways. Here are the seven I see most, each with the symptom, the cause, and the fix.
1. Hardcoded API keys that work locally and 401 in production
The model wrote const apiKey = "sk-abc123..." and it worked because that key was valid when it was generated. In production the key is rotated, rate-limited, or simply the wrong environment's key — and every call returns 401 Unauthorized. The fix is to read keys from the environment and set them on your host:
- const apiKey = "sk-abc123..."
+ const apiKey = process.env.OPENAI_API_KEY
+ if (!apiKey) throw new Error("OPENAI_API_KEY is not set")That throw is deliberate: fail loudly at startup if a required variable is missing, instead of mysteriously at 2am on a user's request.
2. SQLite in production (your data vanishes on deploy)
Symptom: users register, everything works, then after your next deploy every account is gone. Cause: SQLite writes to a file on a filesystem that most hosts treat as disposable. Every deploy ships a fresh container and the file — with all your data — is gone. Switch to a managed Postgres and put the connection string in an env var. This is common enough that it gets its own treatment in the production readiness checklist.
3. Missing CORS configuration
Your frontend calls your API and the browser console shows:
Access to fetch at 'https://api.yourapp.com/data' from origin
'https://yourapp.com' has been blocked by CORS policy: No
'Access-Control-Allow-Origin' header is present on the requested resource.On localhost everything shared one origin, so CORS never applied. In production your frontend and API are on different origins and the browser enforces it. Configure it explicitly — and do not reflexively allow * if you send credentials:
app.use(cors({
origin: ["https://yourapp.com"],
credentials: true,
}))4. The backend was never actually hosted
This one catches non-developers constantly. You deployed to a static host (Netlify, GitHub Pages, Vercel's static output) and the site loads — but every API call 404s, because static hosts serve files, not a running server. Your Express/FastAPI/Rails backend needs a host that runs a long-lived process. Symptom is a perfect-looking frontend where nothing that touches the server works. The fix is deploying the backend to an actual application host and pointing the frontend at its URL.
5. No migrations, so the production schema doesn't exist
Locally your ORM created tables on the fly. In production you get:
error: relation "users" does not existThe tables were never created because the schema only ever lived on your machine. You need migrations that run as part of deployment:
# In your deploy/release step, before the app starts
npx prisma migrate deploy
# or
python manage.py migrateVersion your schema in the repo and run it on deploy, and a brand-new environment builds itself correctly every time.
6. No process manager (one crash and you're down)
You started the app with node index.js in an SSH session. It works until the first unhandled exception kills the process — and nothing restarts it. Production needs a supervisor that restarts on crash and on reboot. If you run your own box, that is systemd or pm2:
# systemd unit: /etc/systemd/system/app.service
[Service]
ExecStart=/usr/bin/node /srv/app/index.js
Restart=always
RestartSec=2
EnvironmentFile=/srv/app/.env
[Install]
WantedBy=multi-user.targetManaged platforms do this for you — which is a big part of what you pay them for. Either way, "a human left an SSH session open" is not a deployment strategy.
7. Your .env is committed to the repo
The mirror image of failure #1: the app works because the secrets are right there in the repo — which means they are also in your git history, and if the repo is public, in the hands of bots that scan GitHub for exactly this. Check and fix:
# Is it tracked?
git ls-files | grep -E "\.env"
# If yes: stop tracking it, then rotate every key it contained
git rm --cached .env
echo ".env" >> .gitignore
git commit -m "Remove committed .env"Removing the file from the latest commit does not remove it from history — assume anything that was ever committed is compromised and rotate those keys at the provider.
The pattern behind all seven
Notice what these share: none of them are bugs in the application logic the AI wrote. They are all about the boundary between your app and the environment it runs in — configuration, state, networking, and process lifecycle. AI code generators are genuinely good at the logic and almost entirely silent about the boundary, because that boundary depends on where you deploy, and they don't know.
Work down this list and most "it broke in production" mysteries resolve. If you want the ML-specific version of the same story, cold starts and GPU quirks get their own list in the guide to deploying models as APIs. And if you would rather not become an infrastructure debugger to ship a weekend idea, handing the deployment off end-to-end is a perfectly good option.
Rather have someone handle this end-to-end?
If you'd rather not become an infrastructure engineer to ship your project, we take a GitHub repo and handle the whole deployment — managed for you, or inside your own AWS, GCP, or Azure. No developer needed on your side.
Get your project deployed →