<?xml version="1.0" encoding="UTF-8"?>
<rss version="2.0" xmlns:atom="http://www.w3.org/2005/Atom" xmlns:dc="http://purl.org/dc/elements/1.1/">
  <channel>
    <title>DEV Community: Alex</title>
    <description>The latest articles on DEV Community by Alex (@alex_pirate_e167052f0b795).</description>
    <link>https://dev.to/alex_pirate_e167052f0b795</link>
    <image>
      <url>https://media2.dev.to/dynamic/image/width=90,height=90,fit=cover,gravity=auto,format=auto/https:%2F%2Fdev-to-uploads.s3.us-east-2.amazonaws.com%2Fuploads%2Fuser%2Fprofile_image%2F4051300%2F96ad08ee-bc5a-4565-a6b9-4bb8af30543d.png</url>
      <title>DEV Community: Alex</title>
      <link>https://dev.to/alex_pirate_e167052f0b795</link>
    </image>
    <atom:link rel="self" type="application/rss+xml" href="https://dev.to/feed/alex_pirate_e167052f0b795"/>
    <language>en</language>
    <item>
      <title>How We Reduced Vercel Edge Requests &amp; CPU Costs by 80% on a Next.js App Router Site</title>
      <dc:creator>Alex</dc:creator>
      <pubDate>Tue, 28 Jul 2026 12:09:11 +0000</pubDate>
      <link>https://dev.to/alex_pirate_e167052f0b795/how-we-reduced-vercel-edge-requests-cpu-costs-by-80-on-a-nextjs-app-router-site-gh2</link>
      <guid>https://dev.to/alex_pirate_e167052f0b795/how-we-reduced-vercel-edge-requests-cpu-costs-by-80-on-a-nextjs-app-router-site-gh2</guid>
      <description>&lt;p&gt;When building a fast-growing web application, hitting unexpected cloud tier limits is a rite of passage. &lt;/p&gt;

&lt;p&gt;Recently, on our platform &lt;strong&gt;&lt;a href="https://cardcheck.in/?utm_source=devto&amp;amp;utm_medium=referral&amp;amp;utm_campaign=vercel_nextjs_case_study" rel="noopener noreferrer"&gt;CardCheck&lt;/a&gt;&lt;/strong&gt;—a web app designed to help Indian consumers compare credit card reward rates, lounge perks, and forex fees—we received a warning alert from Vercel:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;
&lt;strong&gt;Fluid Active CPU:&lt;/strong&gt; 9.3 hours consumed (vs. 4.0 hours included on the Hobby tier — over 230% of our limit).&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;Edge Requests:&lt;/strong&gt; Surging past 980,000+ requests per month (approaching the 1M limit).&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;Our traffic was growing, but our serverless usage was growing exponentially faster. Here is how we pinpointed the root causes, optimized our Next.js App Router codebase, and slashed our daily resource burn by over 80% in under an hour.&lt;/p&gt;




&lt;h2&gt;
  
  
  The Root Causes
&lt;/h2&gt;

&lt;p&gt;After analyzing our route traffic and execution logs, we discovered three main culprits:&lt;/p&gt;

&lt;h3&gt;
  
  
  1. Auth Middleware Running on Guest Traffic
&lt;/h3&gt;

&lt;p&gt;Like many Next.js applications, we use middleware for session handling. However, our middleware function was refreshing authentication state on &lt;em&gt;every single incoming HTTP request&lt;/em&gt;. &lt;/p&gt;

&lt;p&gt;Since 95%+ of visitors browsing credit card comparisons are unauthenticated guests, our serverless middleware was making unnecessary remote authentication checks on every page hit.&lt;/p&gt;

&lt;h3&gt;
  
  
  2. Over-using &lt;code&gt;export const dynamic = 'force-dynamic'&lt;/code&gt;
&lt;/h3&gt;

&lt;p&gt;To ensure card comparison tools and public wallet routes showed fresh data, several pages were explicitly configured with &lt;code&gt;export const dynamic = 'force-dynamic'&lt;/code&gt;. &lt;/p&gt;

&lt;p&gt;This completely bypassed Vercel’s Edge CDN cache, forcing Next.js to execute a serverless function render on every request—including search engine crawlers and automated bots.&lt;/p&gt;

&lt;h3&gt;
  
  
  3. Middleware Matcher Sweeping Up Static &amp;amp; Metadata Assets
&lt;/h3&gt;

&lt;p&gt;Our middleware matcher pattern wasn't explicitly excluding metadata assets like &lt;code&gt;robots.txt&lt;/code&gt;, &lt;code&gt;sitemap.xml&lt;/code&gt;, and static media files. Every time a web crawler indexed our sitemap, it triggered a middleware serverless invocation.&lt;/p&gt;




&lt;h2&gt;
  
  
  The 3-Step Fix
&lt;/h2&gt;

&lt;p&gt;Here is the exact code pattern we implemented to solve these bottlenecks:&lt;/p&gt;

&lt;h3&gt;
  
  
  Step 1: Add a Cookie Guard to Middleware
&lt;/h3&gt;

&lt;p&gt;Instead of triggering session verification for every visitor, we added a lightweight cookie check. If no authentication cookies are present on the incoming request, we skip the remote auth check entirely and return the response immediately.&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight typescript"&gt;&lt;code&gt;&lt;span class="c1"&gt;// middleware.ts&lt;/span&gt;
&lt;span class="k"&gt;export&lt;/span&gt; &lt;span class="k"&gt;async&lt;/span&gt; &lt;span class="kd"&gt;function&lt;/span&gt; &lt;span class="nf"&gt;updateSession&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nx"&gt;request&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="nx"&gt;NextRequest&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
  &lt;span class="kd"&gt;let&lt;/span&gt; &lt;span class="nx"&gt;response&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="nx"&gt;NextResponse&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;next&lt;/span&gt;&lt;span class="p"&gt;({&lt;/span&gt; &lt;span class="nx"&gt;request&lt;/span&gt; &lt;span class="p"&gt;});&lt;/span&gt;

  &lt;span class="c1"&gt;// Guard: Only verify session if auth cookies actually exist on the request&lt;/span&gt;
  &lt;span class="kd"&gt;const&lt;/span&gt; &lt;span class="nx"&gt;hasAuthCookie&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="nx"&gt;request&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;cookies&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;getAll&lt;/span&gt;&lt;span class="p"&gt;().&lt;/span&gt;&lt;span class="nf"&gt;some&lt;/span&gt;&lt;span class="p"&gt;((&lt;/span&gt;&lt;span class="nx"&gt;c&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt; &lt;span class="o"&gt;=&amp;gt;&lt;/span&gt; &lt;span class="nx"&gt;c&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;name&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;startsWith&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="s1"&gt;sb-&lt;/span&gt;&lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="p"&gt;));&lt;/span&gt;

  &lt;span class="k"&gt;if &lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nx"&gt;hasAuthCookie&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
    &lt;span class="c1"&gt;// Refresh session for logged-in user&lt;/span&gt;
    &lt;span class="k"&gt;await&lt;/span&gt; &lt;span class="nf"&gt;refreshUserSession&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nx"&gt;request&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="nx"&gt;response&lt;/span&gt;&lt;span class="p"&gt;);&lt;/span&gt;
  &lt;span class="p"&gt;}&lt;/span&gt;

  &lt;span class="k"&gt;return&lt;/span&gt; &lt;span class="nx"&gt;response&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;
&lt;span class="p"&gt;}&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;&lt;em&gt;Result:&lt;/em&gt; Unauthenticated visitors now get instant responses without waiting on external network hops inside middleware.&lt;/p&gt;




&lt;h3&gt;
  
  
  Step 2: Refactor Middleware Matcher Rules
&lt;/h3&gt;

&lt;p&gt;We updated our &lt;code&gt;middleware.ts&lt;/code&gt; configuration matcher to strictly exclude static assets, sitemaps, and robots.txt:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight typescript"&gt;&lt;code&gt;&lt;span class="k"&gt;export&lt;/span&gt; &lt;span class="kd"&gt;const&lt;/span&gt; &lt;span class="nx"&gt;config&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
  &lt;span class="na"&gt;matcher&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="p"&gt;[&lt;/span&gt;
    &lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="s1"&gt;/((?!_next/static|_next/image|favicon.ico|robots.txt|sitemap.*&lt;/span&gt;&lt;span class="se"&gt;\\&lt;/span&gt;&lt;span class="s1"&gt;.xml|.*&lt;/span&gt;&lt;span class="se"&gt;\\&lt;/span&gt;&lt;span class="s1"&gt;.(?:svg|png|jpg|jpeg|gif|webp|css|js|woff|woff2|ttf|txt|xml|json)$).*)&lt;/span&gt;&lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;
  &lt;span class="p"&gt;],&lt;/span&gt;
&lt;span class="p"&gt;};&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;






&lt;h3&gt;
  
  
  Step 3: Replace &lt;code&gt;force-dynamic&lt;/code&gt; with Incremental Static Regeneration (ISR)
&lt;/h3&gt;

&lt;p&gt;Instead of forcing dynamic SSR on public comparison routes and sitemaps, we switched to Incremental Static Regeneration using &lt;code&gt;revalidate&lt;/code&gt;.&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;Before:&lt;/strong&gt;&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight typescript"&gt;&lt;code&gt;&lt;span class="c1"&gt;// Forces full SSR execution on every request&lt;/span&gt;
&lt;span class="k"&gt;export&lt;/span&gt; &lt;span class="kd"&gt;const&lt;/span&gt; &lt;span class="nx"&gt;dynamic&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="s1"&gt;force-dynamic&lt;/span&gt;&lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;&lt;strong&gt;After:&lt;/strong&gt;&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight typescript"&gt;&lt;code&gt;&lt;span class="c1"&gt;// Pre-renders page at Edge CDN and revalidates in background every 60 seconds&lt;/span&gt;
&lt;span class="k"&gt;export&lt;/span&gt; &lt;span class="kd"&gt;const&lt;/span&gt; &lt;span class="nx"&gt;revalidate&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="mi"&gt;60&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;
&lt;span class="k"&gt;export&lt;/span&gt; &lt;span class="kd"&gt;const&lt;/span&gt; &lt;span class="nx"&gt;dynamicParams&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="kc"&gt;true&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;For sitemaps and metadata files that change infrequently, we set &lt;code&gt;revalidate = 86400&lt;/code&gt; (24 hours).&lt;/p&gt;




&lt;h2&gt;
  
  
  The Results
&lt;/h2&gt;

&lt;p&gt;Within 24 hours of deploying these changes to production on &lt;strong&gt;&lt;a href="https://cardcheck.in/?utm_source=devto&amp;amp;utm_medium=referral&amp;amp;utm_campaign=vercel_nextjs_case_study" rel="noopener noreferrer"&gt;CardCheck&lt;/a&gt;&lt;/strong&gt;:&lt;/p&gt;

&lt;ol&gt;
&lt;li&gt;
&lt;strong&gt;Daily Edge Requests dropped by ~80%&lt;/strong&gt; (from ~89,000 requests/day down to ~12,000 requests/day).&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;Fluid CPU hours stabilized&lt;/strong&gt; well within normal limits.&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;Time to First Byte (TTFB)&lt;/strong&gt; for guest visitors improved by 150–400ms because requests no longer stall in auth middleware.&lt;/li&gt;
&lt;/ol&gt;




&lt;h2&gt;
  
  
  Key Takeaways for Next.js Developers
&lt;/h2&gt;

&lt;ul&gt;
&lt;li&gt;
&lt;strong&gt;Check your Middleware Matcher:&lt;/strong&gt; Ensure static assets and sitemaps aren't silently triggering serverless function invocations.&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;Guard your Auth Checks:&lt;/strong&gt; Don't hit external auth services in middleware if the user doesn't even have a session cookie.&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;Embrace ISR:&lt;/strong&gt; Unless a page requires real-time user-specific data, prefer &lt;code&gt;revalidate&lt;/code&gt; over &lt;code&gt;force-dynamic&lt;/code&gt;.&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;&lt;em&gt;This optimization was built and tested live for &lt;a href="https://cardcheck.in/?utm_source=devto&amp;amp;utm_medium=referral&amp;amp;utm_campaign=vercel_nextjs_case_study" rel="noopener noreferrer"&gt;CardCheck.in&lt;/a&gt;, an unbiased credit card comparison engine for India.&lt;/em&gt;&lt;/p&gt;

&lt;h1&gt;
  
  
  nextjs #webdev #react #performance
&lt;/h1&gt;

</description>
      <category>nextjs</category>
      <category>performance</category>
      <category>webdev</category>
    </item>
  </channel>
</rss>
