2. Localhost vs production

Your app runs on localhost:5000. Your own computer provides everything it needs. When you deploy it, several things change, and some of them need your attention.

Some of what you gain is automatic. Railway gives you a public address, keeps the app running around the clock, and serves it over HTTPS without extra setup.

Concern Localhost Railway gives you
Access Private: 127.0.0.1, your machine only Public: https://your-app.up.railway.app
Uptime Stops when you close your laptop Runs continuously, with automatic restarts
Encryption Plain HTTP HTTPS, provisioned for you

The other half needs more care. Your laptop was quietly doing several jobs on your behalf. Those details do not carry over automatically, so you have to configure them again on Railway. If you miss one, the app may fail even though the code itself is fine.

Concern Localhost Railway needs from you
Storage Local disk, persists by default A persistent /data volume for SQLite
Secrets .env file on your machine Environment variables in the Railway dashboard
OAuth redirect http://127.0.0.1:5000/callback https://your-app.up.railway.app/callback
Debug mode Useful while developing locally Turned off for production

The second table is where deployments usually break. Production does not inherit your laptop's environment. When your code lands on Railway, it runs in a clean container. It does not know about your local database file, your local .env file, or your localhost Spotify callback unless you configure those pieces again.

Deployment pitfalls

Most first deployment errors are not Python errors. They are missing setup errors.

  • If Railway cannot find your Spotify credentials, the app cannot complete OAuth.
  • If Spotify still points to 127.0.0.1, the live login flow redirects to your laptop instead of your deployed app.
  • If SQLite writes to the wrong path, your data may disappear when the container restarts.
  • If debug mode is left on, the app exposes development behaviour in production.

The goal of this chapter is to make each of those hidden local details explicit before they turn into confusing deployment failures.

Platform choice: Railway

You have three good platform options: Railway, Render, and PythonAnywhere. Each has strengths. For this chapter, we're deploying to Railway because it offers the smoothest experience for Flask applications with SQLite databases.

Railway detects Python projects automatically, provides persistent storage with one click, and keeps your app running without the cold-start delays some free hosting tiers introduce. Its Hobby plan includes $5 of monthly usage, enough for a small portfolio project if you keep an eye on usage. The deployment workflow mirrors professional CI/CD practices: push to GitHub, Railway deploys automatically.

Other platforms work too. If you need PostgreSQL eventually, Render includes it. If you don't have a credit card, PythonAnywhere requires none. The deployment patterns you learn transfer across platforms; Railway just gets you deployed fastest with the fewest obstacles, which is what matters for a portfolio piece you want a recruiter to click today, not next week.

Section 3 starts the production-prep work: environment-based config, fail-fast secret validation, the Procfile start command and requirements.txt Railway needs to build your container.