Firewall Rules
Sneaker resellers run bots. The bots scrape inventory endpoints to find drops the moment they're in stock, then they buy the entire allocation before anyone else can. By the time a real customer hits Check Stock, the size they wanted is gone. Three weeks later it's listed at three times retail on a resale site.
Saturday's stock-check endpoint is, right now, an open buffet. Anyone, bot or human, can hit it as many times per second as they want. There's no auth, no throttle, nothing between the public internet and a function that has to do real work for every request.
That's a rate limit waiting to happen. We'll add one in the dashboard. No redeploy.
Outcome
Requests to POST /api/stock-check are limited to 30 per minute per IP. Anything past that gets a 429 response.
Hands-on exercise 2.3
Create a single firewall rule that rate-limits the stock-check route.
Requirements:
- Open Saturday in the dashboard and open the Firewall section
- Click Configure, then + New Rule
- Name the rule
rate-limit-stock-check - Set the condition to match: path equals
/api/stock-check, method equalsPOST - Set the action to Rate Limit: 30 requests per 60 seconds, identified by IP address
- Set the rate-limit response to 429 Too Many Requests
- Save the rule, then click Review Changes and Publish. A saved rule is a draft; only published rules run. Your first rate-limit rule also pops a pricing confirmation dialog, click Continue through it.
Implementation hints:
- Conditions in Vercel's WAF use a clean builder UI. You're not writing regex. If you want exactness, set path to "equals" rather than "contains." A "contains" match on
/api/stock-checkwould also match a hypothetical/api/stock-check-v2, which probably isn't what you want for Saturday. - IP-based rate limiting is a coarse instrument. A shared NAT can put hundreds of legitimate users behind one IP, and a bot operator with a residential proxy network can rotate through thousands of IPs. Counters are also tracked per region, so a globally distributed botnet can exceed the per-IP number in aggregate. For a small indie brand the IP rule does real work; for a target the size of a major drop, you'd layer Bot Protection on top of it. We turn that on in Lesson 2.4.
- Published rules take effect immediately. You don't have to redeploy to test them.
- Hobby allows a handful of custom rules and exactly one rate-limiting rule per project; Pro raises both limits. For this lesson, one rule is plenty.
Try It
Send a burst of requests to the stock-check endpoint from your terminal. Replace YOUR_DOMAIN with Saturday's production URL.
for i in {1..40}; do
curl -s -o /dev/null -w "%{http_code}\n" \
-X POST https://YOUR_DOMAIN/api/stock-check \
-H "Content-Type: application/json" \
-d '{"sku":"sat-foundry-onyx","size":10}'
doneThe first 30-ish responses should be 200. Past that you should see 429:
200
200
200
...
200
200
429
429
429
429
The exact transition point depends on timing. Vercel counts in fixed 60-second windows on Hobby and Pro, so where in the window your loop starts decides exactly when the 429s begin.
Now wait 60 seconds and try one more request. You should see 200 again. The window has passed.
Done-When
- Saturday > Firewall > Rules shows
rate-limit-stock-checkas published, not draft - The rule targets
POST /api/stock-checkonly - Curl loop produces 429 responses after the 30th request
- After 60 seconds, requests succeed again
Troubleshooting
Every request returns 200, even past the 30th.
A few possibilities. The rule might be set to log-only instead of rate limit; open the rule and confirm the action. The more common miss: you saved the rule but never clicked Review Changes and Publish, so it's sitting in a draft. Publish it and run the loop again.
Every request returns 429, including the first one.
You probably triggered the limit before the test, perhaps while clicking around. Wait 60 seconds and try again.
The dashboard shows 429s but a fresh curl returns 200.
Vercel's WAF is per-IP. If you're testing from a different network than the one that triggered the limit, you get a fresh budget. Try from the same machine you saw the 429s from.
Solution
The output of this lesson is a single active rule in Saturday's Firewall. There's no code to push.
The rule in plain English:
When: POST request to /api/stock-check
Limit: 30 requests per 60 seconds per IP
Action: Return 429 Too Many Requests
The drop-launch webhook isn't rate-limited. It probably should be, it's hit infrequently and from known sources, so a tighter limit (5 per minute) would be appropriate there. One catch: Hobby allows a single rate-limiting rule per project, so on Hobby you'd fold the webhook path into this rule's conditions instead of adding a second rule. On Pro, the second rule is a one-minute exercise. Try whichever your plan allows.
Up next: rate limits handle the volume problem. Bot Protection handles the "is this even a real visitor" problem.
Was this helpful?