Express.js Deploying Express Apps

Deployment moves your Express app from your local computer to a server on the internet so anyone in the world can access it. This final topic covers preparing your app for production, choosing a hosting platform, deploying successfully, and keeping the server running reliably after launch.

Development vs Production: Key Differences

┌──────────────────────────────────────────────────────────────┐
│           Development vs Production Comparison               │
├─────────────────────────┬────────────────────────────────────┤
│ Development             │ Production                         │
├─────────────────────────┼────────────────────────────────────┤
│ Runs on localhost       │ Runs on a public server            │
│ Restarts manually       │ Restarts automatically on crash    │
│ Uses nodemon            │ Uses PM2 or platform process mgr   │
│ .env file on disk       │ Env vars set in platform settings  │
│ Shows error stack trace │ Hides sensitive error details      │
│ No HTTPS needed         │ HTTPS required                     │
│ PORT: 3000              │ PORT: 80 or 443                    │
└─────────────────────────┴────────────────────────────────────┘

Step 1: Prepare Your App for Production

Set NODE_ENV to production

Your app should behave differently in production. Check this variable throughout your code to disable debug logs and hide error stack traces from users.

Update package.json scripts

{
  "scripts": {
    "start": "node app.js",
    "dev": "nodemon app.js"
  }
}

Cloud platforms call npm start to run your app. Make sure the start script uses node, not nodemon.

Specify the Node.js version

{
  "engines": {
    "node": ">=18.0.0"
  }
}

This tells the platform which Node.js version your app needs.

Add a .gitignore

node_modules/
.env
*.log

Step 2: Choose a Hosting Platform

┌─────────────────────────────────────────────────────────────────┐
│              Popular Hosting Options for Express                │
├──────────────┬──────────────────────────────────────────────────┤
│ Platform     │ Best For                                         │
├──────────────┼──────────────────────────────────────────────────┤
│ Railway      │ Easy deployment, beginner-friendly, free tier    │
│ Render       │ Auto-deploy from GitHub, free tier available     │
│ Fly.io       │ Containers, global regions, good free tier       │
│ Heroku       │ Established platform, paid plans only            │
│ DigitalOcean │ VPS — full control, more setup required          │
│ AWS EC2      │ Enterprise, full control, more complex           │
│ Vercel       │ Primarily serverless, works with Express         │
└──────────────┴──────────────────────────────────────────────────┘

Step 3: Deploy to Render (Step-by-Step)

Render is beginner-friendly, auto-deploys from GitHub, and has a free tier. Here is the complete process:

1. Push your code to a GitHub repository
   git init
   git add .
   git commit -m "Initial commit"
   git remote add origin https://github.com/yourusername/your-repo.git
   git push -u origin main

2. Visit render.com and create a free account

3. Click "New" → "Web Service"

4. Connect your GitHub repository

5. Configure the service:
   Name:         my-express-app
   Environment:  Node
   Build Command: npm install
   Start Command: npm start
   Plan:          Free

6. Add Environment Variables:
   Click "Environment" → Add each variable:
   NODE_ENV    = production
   MONGODB_URI = mongodb+srv://...
   JWT_SECRET  = your_secret_here
   PORT        = 10000

7. Click "Create Web Service"
   Render builds and deploys automatically

8. Your app is live at:
   https://my-express-app.onrender.com

Step 4: Deploy to Railway (Alternative)

1. Visit railway.app and sign in with GitHub

2. Click "New Project" → "Deploy from GitHub Repo"

3. Select your repository

4. Railway auto-detects Node.js and runs npm start

5. Go to "Variables" tab → add:
   NODE_ENV    = production
   MONGODB_URI = your_connection_string
   JWT_SECRET  = your_secret

6. Click "Settings" → "Generate Domain" to get a public URL

7. Every git push to main auto-deploys

Step 5: Keep the Server Running with PM2

On a VPS (like DigitalOcean), you run your own server. Use PM2 — a process manager that keeps your app alive after crashes and server reboots:

npm install -g pm2

# Start your app with PM2
pm2 start app.js --name "my-express-app"

# Make it survive server reboots
pm2 startup
pm2 save

# Useful PM2 commands
pm2 list              # Show all running processes
pm2 logs              # View app logs
pm2 restart app       # Restart the app
pm2 stop app          # Stop the app
pm2 monit             # Real-time monitoring dashboard

Step 6: Set Up nginx as a Reverse Proxy (VPS only)

On a VPS, nginx sits in front of your Express app. It handles HTTPS, serves static files efficiently, and forwards API requests to Express running on port 3000:

User Browser
     │
     │ HTTPS port 443
     ▼
  [nginx]  ← handles SSL certificate, compression
     │
     │ HTTP port 3000 (internal only)
     ▼
[Express App]  ← only handles application logic

Basic nginx configuration:

server {
    listen 80;
    server_name yourdomain.com www.yourdomain.com;

    location / {
        proxy_pass http://localhost:3000;
        proxy_http_version 1.1;
        proxy_set_header Upgrade $http_upgrade;
        proxy_set_header Connection 'upgrade';
        proxy_set_header Host $host;
        proxy_cache_bypass $http_upgrade;
    }
}

Step 7: Add a Free SSL Certificate with Certbot

HTTPS requires an SSL certificate. Certbot provides free certificates from Let's Encrypt:

sudo apt install certbot python3-certbot-nginx
sudo certbot --nginx -d yourdomain.com -d www.yourdomain.com
# Certbot automatically renews the certificate before it expires

Continuous Deployment: Auto-Deploy on Git Push

Platforms like Render and Railway watch your GitHub repository. Every time you push to the main branch, they automatically build and deploy the latest version:

Developer workflow:
  1. Write code locally
  2. Test with npm run dev
  3. git add . && git commit -m "Fix login bug"
  4. git push origin main
  5. Platform detects push → builds → deploys automatically
  6. App updated in production within ~2 minutes

Health Check Endpoint

Add a /health endpoint that monitoring tools and platforms use to verify your app is running:

app.get('/health', (req, res) => {
  res.status(200).json({
    status: 'healthy',
    uptime: process.uptime(),
    timestamp: new Date().toISOString(),
    environment: process.env.NODE_ENV
  });
});

Production Deployment Checklist

┌──────────────────────────────────────────────────────────────────┐
│                 Pre-Deployment Checklist                         │
├───────────────────────────────────────────────┬──────────────────┤
│ NODE_ENV=production set on platform           │ ✓ or ✗          │
│ All secrets in platform env variables         │ ✓ or ✗          │
│ .env file NOT in repository                   │ ✓ or ✗          │
│ npm start script runs node (not nodemon)      │ ✓ or ✗          │
│ Database connection string correct            │ ✓ or ✗          │
│ CORS configured for production frontend URL   │ ✓ or ✗          │
│ HTTPS working                                 │ ✓ or ✗          │
│ Error stack traces hidden from users          │ ✓ or ✗          │
│ Helmet, rate limiting, sanitization active    │ ✓ or ✗          │
│ Health check endpoint responding              │ ✓ or ✗          │
│ Logging configured (no sensitive data logged) │ ✓ or ✗          │
└───────────────────────────────────────────────┴──────────────────┘

Monitoring After Deployment

After going live, monitoring tells you when things break before users complain:

┌──────────────────────────────────────────────────────────────────┐
│                  Monitoring Tools                                │
├─────────────────┬────────────────────────────────────────────────┤
│ UptimeRobot     │ Free uptime monitoring — alerts when down      │
│ PM2 Monit       │ CPU and memory usage on VPS                    │
│ Sentry          │ Captures and reports application errors        │
│ Logtail         │ Cloud log aggregation and searching            │
│ Render Dashboard│ Built-in metrics on Render platform            │
└─────────────────┴────────────────────────────────────────────────┘

Summary

Deploying Express requires four main steps: prepare your code (set NODE_ENV, clean scripts, add .gitignore), choose a platform (Render and Railway for beginners, DigitalOcean for more control), configure environment variables on the platform, and connect your GitHub repository for automatic deployments. On VPS servers, use PM2 to keep the process alive and nginx as a reverse proxy for HTTPS. Add a /health endpoint for monitoring tools. Use a pre-deployment checklist to verify every security and configuration requirement before going live. Set up monitoring to detect outages and errors immediately after deployment.

Leave a Comment

Your email address will not be published. Required fields are marked *