Deploying the API to Railway
Railway is a platform-as-a-service that deploys Node.js applications from a GitHub repo. It handles servers, scaling, and SSL automatically. (Referral link — signing up through it supports this platform at no cost to you.)
Before you deploy
Section titled “Before you deploy”Make sure your project has:
-
A
startscript inpackage.json:"scripts": {"start": "node dist/index.js","build": "tsc"} -
A
Procfile(optional but explicit):web: npm start -
Your
dist/directory is in.gitignore(Railway will build it). -
The app listens on
process.env.PORT:const PORT = parseInt(process.env.PORT || '3000', 10)app.listen(PORT, ...)
Deploying to Railway
Section titled “Deploying to Railway”-
Push your code to GitHub.
-
Go to railway.com and create a free account.
-
Click New Project → Deploy from GitHub repo → select your
bulletin-apirepository. -
Railway detects Node.js and automatically runs
npm install && npm run build && npm start. -
Click on the deployment → Settings → Variables and add:
NODE_ENV=productionJWT_SECRET=<a long random string — never share this>DATABASE_PATH=./bulletin.dbFRONTEND_URL=https://your-username.github.io -
In the Settings tab, generate a domain (e.g.,
bulletin-api-production.up.railway.app). -
Wait for the deployment to complete — check the build logs for errors.
Verifying the deployment
Section titled “Verifying the deployment”# Health checkcurl https://bulletin-api-production.up.railway.app/health# → { "status": "ok" }
# Register a usercurl -X POST https://bulletin-api-production.up.railway.app/auth/register \ -H "Content-Type: application/json" \ -d '{"username": "testuser", "password": "testpassword"}'# → { "token": "eyJ...", "userId": 1, "username": "testuser" }Important: SQLite in production
Section titled “Important: SQLite in production”SQLite works on Railway but with one limitation: the database file (bulletin.db) is stored on the container’s filesystem. If Railway restarts the container (which it does occasionally), the database persists IF it’s in the project directory committed to git — but it usually isn’t (databases aren’t committed to git).
For a learning project, this is fine. For production apps, you’d use a persistent database service (Railway PostgreSQL, PlanetScale, Supabase, etc.).
Add your bulletin.db to .gitignore and accept that the database may reset on deployment. For learning purposes, this is perfectly acceptable.
Updating the deployment
Section titled “Updating the deployment”Every push to your GitHub main branch triggers a new deployment automatically.
Environment variables summary
Section titled “Environment variables summary”| Variable | Value |
|---|---|
NODE_ENV | production |
JWT_SECRET | Long random string (never commit) |
DATABASE_PATH | ./bulletin.db |
FRONTEND_URL | Your GitHub Pages URL |
PORT | Set automatically by Railway |
Exercise
Section titled “Exercise”- Push your
bulletin-apiproject to GitHub. - Deploy to Railway following the steps above.
- Set all environment variables.
- Test
POST /auth/registeragainst the live URL. - Note the Railway API URL — you’ll use it in Part 2 to configure the React frontend.
- Railway deploys Node.js apps from GitHub repos — auto-detects, auto-builds.
PORTis set by Railway — useprocess.env.PORTin your app.- Set environment variables (JWT_SECRET, FRONTEND_URL) in the Railway dashboard.
- SQLite persists as long as the container doesn’t restart — acceptable for learning, use a managed DB for production.
- Save your Railway URL — the React frontend needs it in Module 08.