Back to Blog

How to Deploy a Node.js App in 2025: The Complete Guide

January 28, 2025

How to Deploy a Node.js App in 2025: The Complete Guide

How to deploy a Node.js app - cloud deployment visualization

Getting your Node.js application from your local machine to production shouldn't be complicated. Yet many developers spend hours wrestling with server configurations, environment variables, and deployment pipelines when they could be shipping features.

This guide walks you through deploying a Node.js app in 2025, comparing the most popular approaches and showing you the fastest path to production.

Why Node.js Deployment Has Changed

The Node.js deployment landscape looks different than it did a few years ago. Heroku eliminated its free tier. AWS complexity keeps growing. And new platforms have emerged that simplify the entire process.

Here's what modern Node.js deployment should look like:

  • Push to GitHub and your app deploys automatically
  • Zero server management - no SSH, no manual updates
  • Built-in SSL without configuration headaches
  • Environment variables managed through a dashboard
  • Instant rollbacks when something goes wrong

If your current workflow doesn't match this, you're working harder than you need to.

Quick Comparison: Where to Deploy Node.js Apps

| Platform | Free Tier | Starting Price | Best For | |----------|-----------|----------------|----------| | Deployra | 512MB RAM, 1 CPU | $10/mo | Full-stack apps, startups | | Heroku | None | $5/mo (Eco) | Legacy apps | | Railway | $5 free credits | Usage-based | Side projects | | Render | 750 hours/mo | $7/mo | Static + API combos | | AWS | Complex limits | ~$15-50/mo | Enterprise scale | | Vercel | Serverless only | $20/mo | Frontend-focused |

Method 1: Deploy Node.js with Deployra (Recommended)

The fastest way to deploy a Node.js app in 2025 is through a modern PaaS that handles infrastructure automatically.

Step 1: Prepare Your Application

Make sure your package.json has a start script:

{
  "name": "my-nodejs-app",
  "version": "1.0.0",
  "scripts": {
    "start": "node server.js",
    "dev": "nodemon server.js"
  },
  "engines": {
    "node": ">=18.0.0"
  }
}

Your app should listen on the PORT environment variable:

const express = require('express');
const app = express();

const PORT = process.env.PORT || 3000;

app.get('/', (req, res) => {
  res.json({ message: 'Hello from Node.js!' });
});

app.listen(PORT, () => {
  console.log(`Server running on port ${PORT}`);
});

Step 2: Connect Your Repository

  1. Sign up at Deployra
  2. Click New Project and select your GitHub repository
  3. Deployra automatically detects your Node.js app

Step 3: Configure Environment Variables

Add any environment variables your app needs through the dashboard:

  • NODE_ENV=production
  • DATABASE_URL (if using a database)
  • API keys and secrets

Step 4: Deploy

Click Deploy and Deployra handles the rest:

  • Installs dependencies with npm install
  • Runs your build command (if specified)
  • Starts your app with npm start
  • Provisions SSL automatically
  • Sets up health checks

Your Node.js app is live in under 2 minutes.

Why Deployra Works Well for Node.js

  • Automatic Node version detection from your engines field
  • Zero-downtime deployments - no dropped requests during updates
  • Built-in logging and monitoring
  • One-click rollbacks to any previous deployment
  • 50% cheaper than comparable platforms

Method 2: Deploy Node.js with Docker

For more control over your runtime environment, containerize your Node.js app.

Create a Dockerfile

FROM node:20-alpine

WORKDIR /app

# Install dependencies first (better caching)
COPY package*.json ./
RUN npm ci --only=production

# Copy application code
COPY . .

# Create non-root user for security
RUN addgroup -g 1001 -S nodejs
RUN adduser -S nodejs -u 1001
USER nodejs

EXPOSE 3000

CMD ["node", "server.js"]

Add a .dockerignore File

node_modules
npm-debug.log
.git
.env

Deploy the Container

Push your Dockerfile to GitHub, and Deployra automatically builds and deploys your container. No Docker registry setup required.

Method 3: Deploy to a VPS (Manual Approach)

If you need full server control, here's the traditional approach using a VPS.

Initial Server Setup

# Update system
sudo apt update && sudo apt upgrade -y

# Install Node.js 20
curl -fsSL https://deb.nodesource.com/setup_20.x | sudo -E bash -
sudo apt install -y nodejs

# Install PM2 for process management
sudo npm install -g pm2

Deploy Your Application

# Clone your repository
git clone https://github.com/yourusername/your-app.git
cd your-app

# Install dependencies
npm ci --only=production

# Start with PM2
pm2 start server.js --name "my-app"
pm2 save
pm2 startup

Set Up Nginx Reverse Proxy

server {
    listen 80;
    server_name 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;
    }
}

Why Most Developers Skip This

Manual VPS deployment requires:

  • Server security hardening
  • SSL certificate management (Let's Encrypt renewal)
  • Firewall configuration
  • Log rotation setup
  • Monitoring and alerting
  • Manual deployment scripts

For most applications, this complexity isn't worth the marginal cost savings.

Configuring Node.js for Production

Regardless of where you deploy, optimize your Node.js app for production.

Enable Trust Proxy

If behind a reverse proxy (most PaaS platforms), configure Express:

const app = express();
app.set('trust proxy', 1);

Handle Graceful Shutdowns

process.on('SIGTERM', () => {
  console.log('SIGTERM received, shutting down gracefully');
  server.close(() => {
    console.log('Process terminated');
    process.exit(0);
  });
});

Set Production Environment

Always set NODE_ENV=production in your deployment. This:

  • Enables Express production optimizations
  • Disables verbose error messages
  • Improves performance

Use Health Check Endpoints

app.get('/health', (req, res) => {
  res.status(200).json({ status: 'healthy' });
});

Adding a Database to Your Node.js App

Most Node.js apps need a database. Here's how to add one.

PostgreSQL with Deployra

  1. Click Add Database in your project dashboard
  2. Select PostgreSQL
  3. Copy the connection string to your environment variables
const { Pool } = require('pg');

const pool = new Pool({
  connectionString: process.env.DATABASE_URL,
  ssl: { rejectUnauthorized: false }
});

MongoDB Atlas (Free Tier Available)

For document databases, MongoDB Atlas offers a free 512MB cluster:

const mongoose = require('mongoose');

mongoose.connect(process.env.MONGODB_URI, {
  useNewUrlParser: true,
  useUnifiedTopology: true
});

Common Node.js Deployment Issues (And Fixes)

"Error: Cannot find module"

Your dependencies didn't install correctly. Check:

  • package-lock.json is committed to your repository
  • No OS-specific dependencies (like bcrypt native builds)
  • Your build command runs npm ci not npm install

App Crashes on Startup

Check your logs for:

  • Missing environment variables
  • Port binding issues (use process.env.PORT)
  • Database connection failures

Memory Issues

Node.js apps can hit memory limits. Solutions:

  • Upgrade your plan for more RAM
  • Add memory limits: node --max-old-space-size=512 server.js
  • Check for memory leaks with --inspect flag

SSL Certificate Errors

When connecting to databases or APIs:

// For development/testing only
process.env.NODE_TLS_REJECT_UNAUTHORIZED = '0';

// Better: Trust the certificate authority
ssl: { rejectUnauthorized: false }

Deployment Checklist for Node.js Apps

Before deploying, verify:

  • [ ] package.json has a start script
  • [ ] App listens on process.env.PORT
  • [ ] All secrets are in environment variables (not code)
  • [ ] NODE_ENV=production is set
  • [ ] Database connections use connection pooling
  • [ ] Error handling doesn't expose stack traces
  • [ ] Health check endpoint exists
  • [ ] Graceful shutdown handlers are implemented

Automating Deployments with GitHub Actions

For teams wanting CI/CD, here's a GitHub Actions workflow:

name: Deploy to Deployra

on:
  push:
    branches: [main]

jobs:
  test:
    runs-on: ubuntu-latest
    steps:
      - uses: actions/checkout@v4
      - uses: actions/setup-node@v4
        with:
          node-version: '20'
          cache: 'npm'
      - run: npm ci
      - run: npm test

  deploy:
    needs: test
    runs-on: ubuntu-latest
    steps:
      - uses: actions/checkout@v4
      - name: Deploy to Deployra
        run: |
          curl -X POST ${{ secrets.DEPLOYRA_WEBHOOK_URL }}

This runs tests on every push and deploys automatically when tests pass.

Scaling Your Node.js Application

When your app grows, you'll need to scale. Modern platforms make this straightforward.

Horizontal Scaling

Add more instances to handle increased traffic:

  • Deployra: Adjust instance count in dashboard
  • Load balancing: Handled automatically
  • Session management: Use Redis for shared sessions

Vertical Scaling

Increase resources per instance:

| Plan | RAM | CPU | Best For | |------|-----|-----|----------| | Free | 512MB | 1 core | Development, testing | | Starter | 1GB | 1 core | Low-traffic apps | | Pro | 2GB | 2 cores | Production workloads | | Scale | 4GB+ | 4+ cores | High-traffic applications |

Next Steps

You now have everything needed to deploy a Node.js app in 2025. The fastest path:

  1. Sign up for Deployra (free tier available)
  2. Connect your GitHub repository
  3. Deploy in under 2 minutes

Stop managing servers. Start shipping features.

Ready to get started with Deployra?