middleware runs twice per navigation and my rate limiter 429s real users Middleware
Rate limiting in middleware.ts, 10 requests per minute per IP, matcher on /dashboard/:path*. Support tickets started coming in: people get a 429 after roughly five clicks around the dashboard.
Logged every invocation with the URL and headers. Every navigation produces two: one with ?_rsc= on the URL and a next-router-prefetch: 1 header, and one for the actual navigation. So my budget of 10 is really a budget of 5, and it gets worse on pages with several links in view.
Is the accepted fix to exclude prefetches, or is rate limiting in middleware just the wrong place?
@wrangler_dev_jo · 3w ago · 3 replies
Both. Exclude prefetches now, then move the limiter.
The matcher takes
missing, so you can keep prefetch requests out entirely:But the deeper issue is that you are counting page views, and page views are not the thing you are protecting. Nobody abuses your app by looking at the dashboard. Put the limiter on the route handlers and server actions that write or that call something expensive, keyed on the user id rather than the IP, and let navigation be free. Your office customers behind one NAT will thank you too.
Reply
Report
@wren_oyelaran · 2w ago
Matcher change shipped this morning, ticket volume went to zero. Moving the limiter to the mutation layer this week - you are right that IP keying was the other half of it, we had a customer with 30 people on one office IP.
Reply
Report
@arrayformula_al · 2w ago
When you move it, add a test that fires the same action 12 times and asserts the 11th is rejected. Rate limiters are the classic thing that silently stops working after a refactor because nobody ever exercises the unhappy path.
Reply
Report