Sunday, May 3, 2026

NestJS on VPS Hangs: Why My “GET /api/v1/users” Returns 502 & How I Fixed It in 30 Minutes While Debugging Logger Misconfiguration and Docker‑Compose Memory Limits

NestJS on VPS Hangs: Why My “GET /api/v1/users” Returns 502 & How I Fixed It in 30 Minutes While Debugging Logger Misconfiguration and Docker‑Compose Memory Limits

If you’ve ever watched a 502 Bad Gateway pop up on a perfectly‑coded NestJS endpoint, you know the feeling—heart‑racing, coffee‑spilled panic, and a million “what‑now?” thoughts. I spent 30 frantic minutes hunting down a silent logger mis‑config and a subtle Docker‑Compose memory cap on a fresh VPS. The result? A rock‑solid /api/v1/users endpoint that now runs smoother than a fresh‑brew espresso.

Why This Matters

When a production API throws a 502, your users can’t log in, your dashboard stalls, and revenue leaks out the backdoor. In the world of SaaS, every second of downtime can cost hundreds of dollars and erode trust. Fixing the issue fast isn’t just a technical triumph—it’s a business imperative.

Step‑by‑Step Tutorial

  1. Reproduce the 502

    From your local machine run:

    curl -i http://YOUR_VPS_IP/api/v1/users

    You’ll see:

    HTTP/1.1 502 Bad Gateway
    Content-Type: text/html; charset=UTF-8
    ...
    
  2. Check Docker‑Compose logs

    The first instinct is docker compose logs, but I discovered the logs were empty because the NestJS logger was pointing at a non‑existent file.

    docker compose logs api
    ... (no output) ...
  3. Fix the Logger Configuration

    Open src/main.ts and replace the faulty logger:

    import { NestFactory } from '@nestjs/core';
    import { AppModule } from './app.module';
    import { Logger } from '@nestjs/common';
    
    async function bootstrap() {
      const app = await NestFactory.create(AppModule, {
        // ❌ Wrong: logger: new Logger('app.log')
        // ✅ Right: use default logger or winston transport
        // logger: new Logger(),
      });
      await app.listen(3000);
    }
    bootstrap();
    Tip: If you need file logging, add winston and configure a transport that actually creates the file.
  4. Inspect Docker‑Compose memory limits

    The api service was limited to 256M which is not enough for NestJS + TypeORM + Swagger in production.

    services:
      api:
        build: .
        ports:
          - "3000:3000"
        deploy:
          resources:
            limits:
              memory: 256M   # ❌ Too low

    Raise it to 512M or more:

              memory: 512M   # ✅ Good for dev, 1G for prod
  5. Rebuild & restart

    Run the following commands:

    docker compose down
    docker compose up --build -d
    docker compose logs -f api

    You’ll now see proper NestJS logs streaming in.

  6. Verify the endpoint

    Run the curl again:

    curl -i http://YOUR_VPS_IP/api/v1/users

    Success!

    HTTP/1.1 200 OK
    Content-Type: application/json; charset=utf-8
    ...
    [{ "id":1,"name":"Alice" },{ "id":2,"name":"Bob" }]

Real‑World Use Case

A fintech startup rolled out a NestJS microservice on a DigitalOcean droplet. Within minutes, customers hit “502 Bad Gateway” on their mobile wallets. The dev team traced the issue back to the same logger mis‑config and a 256M memory cap. After applying the steps above, downtime dropped from 12 minutes to less than 1 minute, and the error vanished.

Results / Outcome

  • ✅ 502 error eliminated – endpoint returns 200 OK
  • ✅ Docker container now uses 512M memory, no OOM kills
  • ✅ Logger writes to console, making future debugging painless
  • ✅ Revenue protection: estimated $1,200 saved per hour of avoided downtime
Bonus Tip: Add restart: unless-stopped to the api service so Docker auto‑restarts after a VPS reboot.

Bonus Tips for Future‑Proofing NestJS on VPS

  • Use pm2 or Docker’s built‑in healthchecks to monitor container health.
  • Store logs in a centralized system (e.g., Loki or Papertrail) instead of local files.
  • Set ulimit -n 65535 on the VPS to avoid “too many open files” errors.
  • Enable sync in docker compose to ensure graceful shutdowns.
Warning: Never set memory limits below the minimum required for Node.js (≈300M). It will cause silent crashes that look like 502s.

Monetization (Optional)

If you’re building SaaS APIs, consider a tiered pricing model that upsells “premium‑support” for fast issue resolution. The time you saved fixing this 502 can be sold as a consulting package—$150/hr for troubleshooting Docker‑Compose mis‑configurations is a realistic rate.

Now you have a repeatable checklist to debug NestJS 502 errors on any VPS. No more vague “server is down” messages—just clear steps, clean code, and peace of mind.

No comments:

Post a Comment