DEV Community

Cover image for I went viral. Then a troll hit my NestJS API 27,000 times. Here is how I survived.
Nexus LMS
Nexus LMS

Posted on

I went viral. Then a troll hit my NestJS API 27,000 times. Here is how I survived.

We all dream of that moment: you post about your side project, it gets picked up by the algorithm, and suddenly you're watching your analytics dashboard light up.

A few weeks ago, my post about my new Full-Stack ERP system went viral on Threads (30k+ views). I was thrilled to see over 14,000 organic requests hitting my backend. My architecture (NestJS + NeonDB) was handling the load beautifully.

But then, the dark side of going viral showed up.

I opened my database console and my heart dropped. A troll had written a script and was aggressively spamming one of my open endpoints. Within hours, they had pumped 27,000 garbage records into my database, trying to exhaust my storage and crash the server.

Here is the story of how my server survived, and how this attack completely changed how I write boilerplate code.

šŸ›”ļø The Trial by Fire: How NestJS Held Up

The good news? The server didn't crash. Not a single HTTP 500 error. The connection pool held up. But having a database filled with 27k junk records is a nightmare.

I quickly realized that while I had built a scalable architecture, I had completely ignored Rate Limiting and Strict Payload Validation on that specific public route.

Here is exactly how I fixed it and secured the app in under 10 minutes:

1. Implementing Global Throttling
I immediately installed @nestjs/throttler to stop brute-force attacks at the gate.

import { Module } from '@nestjs/common';
import { ThrottlerModule, ThrottlerGuard } from '@nestjs/throttler';
import { APP_GUARD } from '@nestjs/core';

@Module({
  imports: [
    ThrottlerModule.forRoot([{
      ttl: 60000, // 1 minute
      limit: 10,  // Max 10 requests per IP
    }]),
  ],
  providers: [
    {
      provide: APP_GUARD,
      useClass: ThrottlerGuard,
    },
  ],
})
export class AppModule {}
Enter fullscreen mode Exit fullscreen mode

2. Hardening the DTOs
The troll was sending massive strings to fill up my DB. I tightened my class-validator rules to ensure nobody could send payloads larger than expected.

import { IsString, MaxLength, IsNotEmpty } from 'class-validator';

export class CreateRecordDto {
  @IsString()
  @IsNotEmpty()
  @MaxLength(100) // The magic shield!
  title: string;
}
Enter fullscreen mode Exit fullscreen mode

After a quick database purge (TRUNCATE TABLE), the endpoint was locked down. The script kiddie kept trying, but the API just threw elegant 429 Too Many Requests errors.
šŸš€ The Epiphany: Automating Security
Surviving this attack taught me a harsh lesson: Setting up rate limiting, strict DTOs, custom Guards, and RBAC from scratch for every single project is a massive waste of time. You forget one @MaxLength() decorator, and your DB is dead.

I got so tired of manually writing this boilerplate that I decided to automate my entire workflow.

I packed all my battle-tested, production-ready NestJS patterns (and React components) into a single VS Code Extension.

Enter Lumina Lite: React, Next.js & NestJS Snippets āš”ļø

Instead of writing a full NestJS CRUD module by hand and praying I didn't forget the security layers, I just type lumina-nest-crud, hit Tab, and instantly get:

  • A fully isolated Domain Module.

  • A Controller protected by AuthGuards.

  • A Service with clean architecture (no direct DB calls!).

  • Extended DTOs with strict validation already imported.

If you build SaaS apps, ERPs, or just want to ship side projects faster without compromising on enterprise-grade security, you can grab the extension for free on the VS Code Marketplace.

(P.S. If you want the ultimate cheat code, the Lite extension also has a link to my Telegram bot where I share my Full Stack Developer Bundle with 100+ premium snippets).

How do you guys protect your public API endpoints when you launch? Let me know in the comments! šŸ‘‡

Top comments (0)