← All posts
rate limitingvibe codingAI code securityexpress-rate-limitAPI abuse prevention

Fix Missing Rate Limiting in AI-Coded Apps: A Practical Guide

O

OverMCP Team

Quick answer

Rate limiting controls how many requests a user or IP can make to your app in a given time. Many AI-coded apps skip it entirely, making them easy targets for brute-force attacks, API abuse, and denial-of-service. To fix missing rate limiting, add a middleware or library to your backend that tracks requests and returns 429 status when limits are exceeded.

What is rate limiting and why vibe-coded apps miss it

When you use tools like Cursor, Bolt.new, or v0 to generate an app quickly, the AI focuses on core functionality—authentication, database queries, UI components. Rate limiting is an "invisible" security measure that often gets left out because:

  • AI models prioritize visible features over operational safeguards.
  • The prompt doesn't explicitly ask for rate limiting.
  • It's seen as "we'll add it later" during rapid prototyping.
  • But without rate limiting, a single user can hammer your login endpoint thousands of times per minute, guess passwords, or drain your API credits. This is especially dangerous for indie makers running on free tiers—one bad actor can cost you real money.

    What to check first

    Before writing code, audit your app for rate limiting gaps:

  • [ ] Do your authentication endpoints (login, signup, password reset) have any request limits?
  • [ ] Are your public API endpoints (e.g., search, data fetch) unthrottled?
  • [ ] Is there a middleware or config file that mentions rate limiting (e.g., express-rate-limit, @nestjs/throttler)?
  • [ ] Have you tested what happens if you send 100 rapid requests to a single endpoint?
  • [ ] Do your serverless functions (Vercel, Netlify) have built-in limits configured?
  • If you answered "no" to any of these, your app likely has missing rate limiting.

    Step-by-step fix

    Here's how to add rate limiting to a Node.js/Express app generated by AI. The same pattern applies to other frameworks.

    1. Install a rate limiting library

    npm install express-rate-limit

    2. Create a rate limiter middleware

    In your server file (e.g., app.js or server.js), import and configure the limiter:

    const rateLimit = require('express-rate-limit');
    
    const limiter = rateLimit({
      windowMs: 15 * 60 * 1000, // 15 minutes
      max: 100, // limit each IP to 100 requests per windowMs
      standardHeaders: true,
      legacyHeaders: false,
      message: { error: 'Too many requests, please try again later.' }
    });
    
    // Apply to all routes
    app.use(limiter);

    3. Apply stricter limits to sensitive endpoints

    const authLimiter = rateLimit({
      windowMs: 15 * 60 * 1000,
      max: 5, // 5 login attempts per 15 minutes
      message: { error: 'Too many login attempts. Try again later.' }
    });
    
    app.post('/api/login', authLimiter, (req, res) => {
      // login logic
    });

    4. Test your implementation

    Use curl or a tool like OverMCP's free security scanner to verify that repeated requests receive a 429 status.

    for i in {1..10}; do curl -X POST http://localhost:3000/api/login -d '{"username":"test","password":"wrong"}' -H "Content-Type: application/json"; done

    5. For serverless environments (Vercel, Netlify)

    If you're deploying on Vercel, you can use the @vercel/rate-limiter helper or implement a custom middleware with Upstash or Redis. For a quick fix, add the express-rate-limit approach inside your API route files—but note that serverless functions are stateless, so you'll need an external store like Redis for accurate counts.

    // Example using Upstash Redis for serverless
    import { Ratelimit } from '@upstash/ratelimit';
    import { Redis } from '@upstash/redis';
    
    const ratelimit = new Ratelimit({
      redis: Redis.fromEnv(),
      limiter: Ratelimit.slidingWindow(10, '10 s'),
    });
    
    export default async function handler(req, res) {
      const ip = req.headers['x-forwarded-for'] || req.connection.remoteAddress;
      const { success } = await ratelimit.limit(ip);
      if (!success) return res.status(429).json({ error: 'Too fast' });
      // ... rest of handler
    }

    Common mistakes

    Even when developers add rate limiting, they often make these errors:

    1. Only limiting by IP

    Attackers can rotate IPs using VPNs or botnets. Combine IP with user ID or session tokens for better accuracy. Use a tool like OverMCP's continuous security monitoring to detect abuse patterns in real time.

    2. Setting limits too high or too low

  • Too high: doesn't stop abuse.
  • Too low: blocks legitimate users. Start with generous limits and tighten based on analytics.
  • 3. Forgetting to limit error responses

    If your login endpoint returns a 429 after 5 attempts, but your password reset endpoint has no limit, attackers will pivot there. Apply rate limiting to all authentication endpoints.

    4. Not returning proper headers

    Standard rate limit headers (X-RateLimit-Limit, X-RateLimit-Remaining) help clients back off gracefully. The express-rate-limit library includes them by default.

    Why this matters for vibe-coded apps

    AI-generated code is often deployed to production faster than traditionally built apps. A missing rate limit can lead to:

  • Billing shock: One attacker hitting your OpenAI API endpoint can rack up thousands in charges.
  • Account takeover: Brute-forcing weak passwords becomes trivial.
  • Data scraping: Competitors can scrape your entire database without restriction.
  • By adding rate limiting, you protect your app, your users, and your wallet. OverMCP can help you scan your app for missing rate limiting as part of a broader security audit.

    FAQ

    How do I know if my vibe-coded app needs rate limiting?

    If your app has any public endpoint that accepts user input, especially authentication or paid API endpoints, you need rate limiting. The easiest way to check is to use a free security scanner that tests for rate limiting gaps.

    Can I add rate limiting after deployment?

    Yes, but it's easier to add it before launch. You can add middleware to your existing app without changing the database or frontend. Just install the library and apply the middleware.

    What's the best rate limiting strategy for a solo developer?

    Start with IP-based limiting using express-rate-limit or a similar library. As your app grows, move to user-based limits with Redis for serverless environments. OverMCP's continuous monitoring can alert you if your limits are being bypassed.

    ---

    This article is part of a series on securing vibe-coded apps. Check out our [Vercel security scanner](https://www.overmcp.com/connect/vercel) for more deployment-specific checks.

    Is your app secure?

    Free scan in 30 seconds. No signup needed.

    Scan My App Free