Sunday, May 3, 2026

Stuck on “NestJS Cannot Connect to PostgreSQL When Deployed to a Shared VPS – My App Crashes at Runtime!”

Stuck on “NestJS Cannot Connect to PostgreSQL When Deployed to a Shared VPS – My App Crashes at Runtime!”

You've spent hours polishing your NestJS API, tested it locally, and everything works like a charm. Then you ship it to your cheap shared VPS, hit npm run start:prod, and—boom—your app crashes with a cryptic “cannot connect to PostgreSQL” error. Panic sets in, logs are a mess, and you wonder if you should just abandon the project.

Why This Matters

In the world of SaaS and freelance dev work, downtime is money lost. A mis‑configured database connection can cost you client trust, hourly revenue, and valuable time you could be spending on new features or side‑hustles. Fixing it fast not only gets your service back online but also shows you know how to troubleshoot production‑grade Node.js apps—something every client loves.

Step‑by‑Step Tutorial

  1. Confirm PostgreSQL Is Running on the VPS

    Log into your VPS via SSH and run:

    systemctl status postgresql

    If the service is inactive, start it:

    sudo systemctl start postgresql
  2. Check Network Bindings

    Shared VPSes often bind PostgreSQL to localhost only. Open /etc/postgresql/12/main/postgresql.conf (version may vary) and make sure:

    listen_addresses = '*'

    Then edit pg_hba.conf to allow your app’s user:

    host    all             all             127.0.0.1/32            md5
    host    all             all             ::1/128                 md5

    Restart PostgreSQL afterwards.

  3. Create a Dedicated Database User

    Never use the default postgres superuser for your app. From the psql prompt:

    CREATE USER nest_user WITH PASSWORD 'SuperSecret123!';
    CREATE DATABASE nestapp OWNER nest_user;
    GRANT ALL PRIVILEGES ON DATABASE nestapp TO nest_user;
  4. Set Up Environment Variables on the VPS

    Production should never hard‑code credentials. Edit your shell profile (e.g., .bashrc) or use a process manager like pm2 to inject:

    export DB_HOST=127.0.0.1
    export DB_PORT=5432
    export DB_USER=nest_user
    export DB_PASS=SuperSecret123!
    export DB_NAME=nestapp
  5. Configure NestJS TypeORM Module

    Update app.module.ts (or a dedicated database.module.ts) to read from the env variables:

    import { Module } from '@nestjs/common';
    import { TypeOrmModule } from '@nestjs/typeorm';
    import * as dotenv from 'dotenv';
    dotenv.config();
    
    @Module({
      imports: [
        TypeOrmModule.forRoot({
          type: 'postgres',
          host: process.env.DB_HOST,
          port: +process.env.DB_PORT,
          username: process.env.DB_USER,
          password: process.env.DB_PASS,
          database: process.env.DB_NAME,
          autoLoadEntities: true,
          synchronize: false, // keep false in prod
        }),
        // …other modules
      ],
    })
    export class AppModule {}
  6. Test the Connection Locally on the VPS

    Run a quick Node script to verify the credentials before launching the full app:

    node -e "require('typeorm').createConnection().then(()=>console.log('✅ Connected')).catch(e=>console.error('❌',e))"

    If the script prints ✅ Connected, you’re good to go.

  7. Deploy with PM2 (or Systemd)

    PM2 keeps your app alive and streams logs:

    npm install -g pm2
    pm2 start dist/main.js --name nestapp --env production
    pm2 save
    pm2 startup
Tip: If your VPS uses a firewall (UFW, iptables), open port 5432 for localhost only. Example for UFW: sudo ufw allow from 127.0.0.1 to any port 5432.

Real‑World Use Case: SaaS Dashboard on a $5/month VPS

Imagine you’re building a small analytics dashboard for a local gym. The client wants a low‑cost solution, so you spin up a $5/month shared VPS, install Ubuntu 22.04, PostgreSQL, and your NestJS API. Following the steps above, the dashboard stays online 24/7, the gym can view member stats, and you earn a recurring $150/month retainer. The key is a rock‑solid DB connection that never surprises you at runtime.

Results / Outcome

After applying the checklist:

  • Zero runtime crashes related to PostgreSQL.
  • Connection latency dropped from ~150ms (mis‑routed) to <15ms (local).
  • PM2 auto‑restarted the app after a server reboot—no manual steps.
  • Client confidence increased, leading to a 20% upsell on additional features.

Bonus Tips

  • Use a .env file for local dev and load it with dotenv. Never commit secrets.
  • Enable SSL on PostgreSQL if you ever move to a cloud host.
  • Monitor with pg_top or pg_stats to catch slow queries before they affect users.
  • Automate backups via pg_dump and a cron job.
Warning: Never set synchronize: true in production. It can drop tables and erase data during a deploy.

Monetization Angle (Optional)

If you’re a freelancer, package this setup as a “Ready‑to‑Deploy NestJS + PostgreSQL starter” and sell it on marketplaces like Gumroad or CodeCanyon. Charge $29 for the code plus a $9/month hosting‑assist subscription, and you’ll create a passive income stream while helping other devs avoid the same nightmare.

© 2026 Your Name • All rights reserved.

No comments:

Post a Comment