Netlify site name: I’d rather not post it publicly while this abuse is ongoing — I don’t want to point more traffic at it. Happy to share privately with a staff member. I’ve also emailed support directly. It’s a Vite SPA, publish dir dist, with one existing edge function.
DNS issues? No. DNS and SSL are fine. Not a domain or certificate problem.
Build problems? No. Builds and deploys succeed normally. The problem is inbound request volume, not the build.
Did you try Ask Netlify? [Answer honestly — if you haven’t, take two minutes and try it first, then say what it told you.]
Plan: Personal, $9/mo, 1,000 credits/month.
redits. I’ve since tested a mitigation myself and want to sanity-check it before shipping, plus there’s one cost question I can’t answer alone.
What happened. Over 24 hours the site took 467,966 requests and 33.5 GB of bandwidth. India accounted for 465,400 requests and 33.35 GB — over 99% of both. My real audience, the US, was 2,100 requests and 82 MB. It’s a local service business in Florida with no market in India. Traffic came in ~13 minute bursts at roughly 137 req/s, then went quiet.
Why it’s clearly automated. Nearly every request used a user agent like Mozilla/5.0 (Linux; Android 10; K) ... Chrome/150.0.0.0 Mobile Safari/537.36, rotated across Chrome versions 131 through 150.
What I tested. Before writing a geo-block I wanted to know whether an edge function even runs on a request the CDN serves from cache — if cached asset hits bypassed the function, blocking there would save no bandwidth at all. So I deployed a throwaway site with an edge function that stamps a unique value into a response header, and hit an asset served with Cache-Control: public, max-age=31536000, immutable repeatedly.
Result: on a request where cache-status reported "Netlify Edge"; hit with age=4, the response still carried a fresh, unique stamp. So the edge function ran even on a cache hit. Good news — the block won’t be bypassed.
I then tested short-circuiting, returning a 403 from the function without calling context.next(). Allowed request: 200, 187 bytes. Blocked request: 403, 7 bytes, and no cache-status header at all, meaning it never reached cache or origin. On my real traffic, which averaged ~72 KB per request, that’s a >99.9% bandwidth reduction.
My actual questions.
The one I can’t answer: does a blocked request still consume an edge function invocation, and how do invocations meter against credits compared to bandwidth? At current volume that’s ~465,000 invocations/day. I want to be sure I’m not trading a bandwidth problem for an invocation problem. If someone knows the real conversion on the Personal plan, that’s the thing I need.
Second: a country block only works until they rotate to proxies elsewhere. Has anyone built durable per-IP rate limiting in a Netlify edge function, and does that hold up at this volume?
Third: is there any way to throttle rather than hard-stop when credits run out? Right now anyone can take my site offline just by sending enough traffic, which worries me more than the credits did.
Happy to share the test edge function code if it’s useful to anyone else — the cache-hit finding surprised me and I couldn’t find it documented clearly.