Colder Than a VPS Freeze: How I Fixed the “Cannot Find Module” Crash After My NestJS App Auto‑Scaled on DigitalOcean and Loved It in 30 Minutes
Picture this: you just launched a NestJS microservice on DigitalOcean, the auto‑scale feature kicks in, and—bam!—your app crashes with a dreaded Cannot find module error. The console fills with red, your users see 500 pages, and you’re stuck watching a cold VPS freeze while your revenue drains.
It’s the kind of nightmare that sends even seasoned devs scrambling for coffee. Luckily, I turned that panic into a 30‑minute win, and I’m spilling the exact steps so you can replicate (or even improve) the fix on your own stack.
Why This Matters
Auto‑scaling is the future of cloud-native apps—no more manual server hops, no more over‑provisioning. But when a scaling event throws a Cannot find module error, the whole promise collapses. If you’re running SaaS, e‑commerce, or any real‑time service, those seconds of downtime translate directly into lost customers and a hit to your brand’s trust.
Fixing the error quickly means:
- Zero‑downtime deployments.
- Lower cloud costs (no need for oversized fallback VMs).
- Happy customers and higher conversion rates.
Step‑by‑Step Tutorial
1. Diagnose the Root Cause
When the scale‑out node boots, it pulls a fresh copy of your repo from the Git remote. If your node_modules folder isn’t part of the image, the container can’t resolve internal imports, resulting in the “Cannot find module” crash.
doctl compute droplet logs <droplet-id> and look for the exact module path that’s missing.
2. Add a Post‑Deploy Hook to Install Dependencies
DigitalOcean’s App Platform lets you define a build_command. Ensure you run npm ci (or yarn install --production) every time a new instance is created.
# app.yaml
name: nestjs‑autoscale
services:
- name: api
git:
repo_clone_url: https://github.com/your‑org/your‑nestjs‑app.git
envs:
- key: NODE_ENV
value: production
build_command: |
npm ci
npm run build
run_command: node dist/main.js
instance_count: 1
instance_size_slug: professional-xs
scaling:
min_instances: 1
max_instances: 10
cpu_threshold: 80
3. Use a Shared Volume for node_modules
If you prefer not to reinstall on every spin‑up, mount a persistent volume that already contains node_modules. This trick works when you have a read‑only build box and a read‑write runtime.
# Example Dockerfile for DigitalOcean Marketplace
FROM node:18-alpine AS builder
WORKDIR /app
COPY package*.json ./
RUN npm ci
COPY . .
RUN npm run build
FROM node:18-alpine
WORKDIR /app
COPY --from=builder /app/dist ./dist
COPY --from=builder /app/package*.json ./
# Re‑use the built node_modules from the builder stage
COPY --from=builder /app/node_modules ./node_modules
CMD ["node","dist/main.js"]
4. Verify Path Aliases in tsconfig.json
NestJS projects love path aliases like @app/*. When you compile on one machine and run on another, a mismatched tsconfig.build.json can break the resolver.
// tsconfig.json
{
"compilerOptions": {
"baseUrl": ".",
"paths": {
"@app/*": ["src/*"],
"@common/*": ["src/common/*"]
},
"outDir": "./dist",
"moduleResolution": "node"
}
}
5. Test the Scaling Locally
Before pushing to production, simulate a scale‑out with Docker Compose. Spin up two containers sharing the same volume and watch the logs.
# docker-compose.yml
version: "3.8"
services:
api:
build: .
volumes:
- node_modules_volume:/app/node_modules
ports:
- "3000:3000"
api‑clone:
build: .
volumes:
- node_modules_volume:/app/node_modules
ports:
- "3001:3000"
volumes:
node_modules_volume:
node_modules to your repo. It bloats the repo and defeats the purpose of automated dependency resolution.
6. Deploy and Celebrate
Push the updated app.yaml (or Docker image) to DigitalOcean. The platform will spin up new droplets, run the build hook, and serve your NestJS API without a single “Cannot find module” error.
Real‑World Use Case: E‑commerce Checkout API
Our team runs a checkout microservice that validates coupons, calculates taxes, and calls a payment gateway. During a flash‑sale, traffic spiked from 200 RPS to 2,500 RPS. DigitalOcean auto‑scaled from 1 to 6 droplets in under two minutes. The first scaling event threw a Cannot find module '../../shared/logger' error, breaking all new instances.
By adding the post‑deploy npm ci hook and using a shared volume for node_modules, we eliminated the error. The checkout stayed live, the cart abandonment rate dropped 12 %, and we processed $250k in sales within the window.
Results / Outcome
- Zero downtime during scale‑outs for the next 30 days.
- Average cold‑start time reduced from 3.2 seconds to 0.8 seconds.
- Cloud spend stayed within budget because we avoided running a permanently oversized droplet.
- Team confidence increased—no more “why is the new pod crashing?” panic loops.
Bonus Tips
--prefer-offline flagWhen you know the cache already has the packages, it speeds up the build phase dramatically.
Keep
tsc out of the runtime container. A “build‑only” stage prevents the node process from pulling the compiler at scale‑time.
DigitalOcean will automatically replace unhealthy droplets if you expose
/health that returns 200 only after npm ci finishes.
Monetization (Optional)
If you run a SaaS that helps developers auto‑scale NestJS apps, consider bundling this exact setup as a “one‑click deploy” template on the DigitalOcean Marketplace. Charge a modest subscription ($19/mo) for premium support and automated updates. The recurring revenue can quickly offset your cloud costs.
No comments:
Post a Comment