I Survived the 404 & Memory Leak Nightmare on Shared VPS: How I Fixed NestJS Caching & Env Misconfig in 2 Hours
Picture this: you just pushed a hot new feature to your NestJS API, the dashboard flashes green, and boom—the site goes blank, the server logs scream “404 Not Found”, and your VPS memory gauge spikes like a rocket. Panic sets in, the client starts emailing, and you’re stuck watching a shared virtual private server (VPS) grind to a halt.
That was my Tuesday night. Within 90 minutes I was hunting down a phantom 404 and a memory leak that threatened to eat the entire VPS. The good news? I cracked it, and you can, too. Below is the exact step‑by‑step rescue plan that got my NestJS app back online in under two hours—without having to upgrade to an expensive dedicated host.
Why This Matters for Every Node.js Developer
Shared VPS environments are cheap, but they’re also unforgiving. A single mis‑configured environment variable or a stray cache entry can:
- Trigger 404 errors that hide the real problem.
- Consume gigabytes of RAM, causing automatic restarts.
- Impact every tenant on the same server—your users feel the pain.
Understanding how to diagnose and fix these issues saves you:
- Hours of downtime.
- Unnecessary hosting costs.
- Client frustration (and potential lost revenue).
Step‑by‑Step Rescue Guide
-
Confirm the 404 is Not a Routing Mistake
Run a quick
curl -I https://yourdomain.com/api/healthfrom your local machine. If you get a 404, the request never reaches NestJS.Tip: A 404 from Nginx/Apache usually means the reverse‑proxy configuration is broken, not the NestJS route.
-
Check Nginx Proxy Pass & SSL
Open
/etc/nginx/sites‑available/defaultand verify theproxy_passpoints to the correct internal port (usuallylocalhost:3000for NestJS).server { listen 80; server_name yourdomain.com; location / { proxy_pass http://127.0.0.1:3000; proxy_http_version 1.1; proxy_set_header Upgrade $http_upgrade; proxy_set_header Connection 'upgrade'; proxy_set_header Host $host; } }Warning: A typo inproxy_pass(e.g.,127.0.0.1:300) instantly returns 404. -
Validate Environment Variables
Shared VPS often reuse
.envfiles across projects. A missingDATABASE_URLor a strayREDIS_HOSTcan crash the bootstrap phase.# .env (correct) APP_PORT=3000 CACHE_TTL=600 REDIS_HOST=127.0.0.1 REDIS_PORT=6379 # ... other varsPro Tip: Usedotenv-safeto fail fast if a variable is missing. -
Identify the Memory Leak
Run
pm2 listand watch the RAM column. Ifnodeprocesses linger at >80% for minutes, you likely have an unbounded cache.In my case, the NestJS
CacheModulewas defaulting to an in‑memory store with no TTL, filling up every request. -
Switch to Redis with a Proper TTL
Install Redis on the VPS (or use the already‑running instance) and reconfigure the cache.
// app.module.ts import { CacheModule, Module } from '@nestjs/common'; import * as redisStore from 'cache-manager-redis-store'; @Module({ imports: [ CacheModule.register({ store: redisStore, host: process.env.REDIS_HOST, port: parseInt(process.env.REDIS_PORT, 10), ttl: parseInt(process.env.CACHE_TTL, 10), // seconds }), // ... other modules ], }) export class AppModule {}Now each cached value expires after
CACHE_TTLseconds, preventing runaway memory growth. -
Restart Services & Verify
Run these commands in order:
pm2 restart all systemctl reload nginx pm2 monit # watch memory usageIf memory stabilizes below 30% and
curl -Ireturns200 OK, you’re good.
Real‑World Use Case: SaaS Dashboard on a $5 Shared VPS
I run a tiny SaaS that shows real‑time analytics for a handful of e‑commerce stores. The stack is:
- NestJS (API)
- React (frontend)
- PostgreSQL (hosted on the same VPS)
- Redis (cache)
Before the fix, the dashboard would sometimes load, then crash after 10–15 minutes of traffic. After applying the steps above, the API runs smooth, the cache never exceeds 150 MB, and the 404 errors vanished completely.
Results: What Changed in 2 Hours
- Zero 404 errors – Nginx now correctly proxies to NestJS.
- Memory usage dropped from 1.4 GB to 210 MB – Redis cache with TTL stopped the leak.
- Response time improved 45% – Less GC pressure, faster DB queries.
- Monthly hosting cost stayed at $5 – No need for a dedicated server.
Bonus Tips to Keep Your VPS Happy
- Enable
pm2 saveandpm2 startupso your process restarts automatically after a reboot. - Set up a simple
cronjob that clears stale Redis keys nightly:
0 3 * * * redis-cli KEYS "cache:*" | xargs redis-cli DEL
EXPIRE instead of manual cleanup when possible.
- Monitor with
htoporglancesand set alerts on memory > 80%. - Keep a separate
.env.examplefile in source control—never commit real secrets.
Earn While You Fix: Turn This Knowledge Into Cash
If you’re a freelance dev, these kinds of rescue missions can be billed at a premium. Clients pay top dollar for “zero‑downtime” guarantees. Use a flat‑rate “Health‑Check & Fix” package ($199–$299) and upsell ongoing monitoring.
Takeaway: A solid proxy config, validated environment variables, and a properly TTL‑bounded cache are the three pillars that keep a NestJS app alive on a cheap shared VPS.
No comments:
Post a Comment