🪟 Windows TippsModify Windows Support Phone Number with PowerShell(03.09.2026 um 00:00 Uhr)
🔧 AI Nachrichten Podcast: ChatGPT schwatzt Nutzern in Deutschland jetzt Werbung auf(28.08.2026 um 08:46 Uhr)
🪟 Windows TippsMicrosoft bringt Emoji 17.0 auf Windows 11(31.08.2026 um 08:16 Uhr)
🪟 Windows TippsModify Windows Support Phone Number with PowerShell(03.09.2026 um 00:00 Uhr)
🔧 AI Nachrichten Podcast: ChatGPT schwatzt Nutzern in Deutschland jetzt Werbung auf(28.08.2026 um 08:46 Uhr)
🪟 Windows TippsMicrosoft bringt Emoji 17.0 auf Windows 11(31.08.2026 um 08:16 Uhr)

🔧 Programmierung 🕛 vor 2 Monaten 3 Min Lesezeit
0

Cutting Vercel Fluid CPU with Next.js Server-Side Caching

↗ Quelle (dev.to)
🗣️ Stimme:
📑 Inhaltsübersicht




Cutting Vercel Fluid CPU with Next.js Server-Side Caching



Got an email from Vercel about reaching limits and checked to see Fluid Active CPU spiking for worldcuppicks.co. Obviously I don't want to go to premium, so I implemented certain measures to bring it down. We are in the knockout rounds now, so I wanted to get it sorted before things got worse.






First identification



Going to the Vercel Observability tab, I was able to see which page was causing the heavy load. The home page function was clocking nearly 3 minutes of active CPU time per billing window while every other route measured in seconds. That pointed me straight at the problem: the home page was doing two full database fetches on every single visit, for every user, with no caching in between.




CODE
// This ran on every page visit, for every user
const [matches, predictions] = await Promise.all([
getAllMatches(),
getAllMatchPredictions(),
]);






getAllMatches joins across three tables. getAllMatchPredictions pulls aggregate pick stats. Both were uncached, so every visit hit the database from scratch.



The second culprit was Sentry. I had it configured with a tunnelRoute that proxies Sentry events through a Vercel function at /monitoring. Every page load was generating an extra function invocation. I disabled Sentry entirely for now and that brought the baseline down.






The fix: unstable_cache



Next.js ships a function called unstable_cache that wraps any async function with a server-side cache. The result is shared across all users and all requests, not per session. The first request after a cache miss hits the database, and every subsequent request gets the cached result.



For matches I set revalidate: false, meaning the cache never expires on a timer:




CODE
export const getAllMatches = unstable_cache(
async (): Promise<Match[]> => {
const supabase = getOrCreateAdminClient();
const { data } = await supabase
.from("matches")
.select(`*, home_team:teams!home_team_id(...), away_team:teams!away_team_id(...)`)
.order("match_date", { ascending: true });
return (data as Match[]) ?? [];
},
["all-matches"],
{ revalidate: false, tags: ["matches"] }
);






Match data only changes when I update it from the admin panel, so a time-based TTL adds nothing. The admin server action calls revalidateTag("matches") the moment a match is saved, which busts the cache immediately:




CODE
const { error } = await supabase.from("matches").update(update).eq("id", matchId);
if (error) throw new Error("Failed to update match");
revalidatePath("/admin");
revalidateTag("matches");
revalidateTag("predictions");






For prediction stats I went with a one-hour TTL as a fallback:




CODE
export const getAllMatchPredictions = unstable_cache(
async (): Promise<MatchPredictionStats[]> => {
const supabase = getOrCreateAdminClient();
const { data } = await supabase.from("match_predictions").select("*");
return (data ?? []) as MatchPredictionStats[];
},
["all-match-predictions"],
{ revalidate: 3600, tags: ["predictions"] }
);









Why stale prediction stats are fine



The obvious concern is that cached prediction percentages go stale. Won't someone loading the page see wrong crowd percentages?



But the crowd percentage bar uses a Supabase realtime subscription on the client. The moment a pick is submitted, Supabase pushes the updated row to every connected browser over a WebSocket. The cached server data is only used for the initial SSR render. Within milliseconds of hydration, realtime takes over.



The user's own pick is handled via optimistic local state, so it's instant regardless:




CODE
async function handlePick(newPick: Pick) {
setPick(newPick); // instant, before the server action returns
await submitPrediction(matchId, newPick);
}









The key insight



unstable_cache is shared across all requests on the server, not per session. Without it, every page visit queries the database for the exact same data. With it, it's one query until the cache is busted. For match data that only changes when I update it from the admin panel, that's the right trade.



Happy coding!

Vollständiger Original-Bericht
Ausführliche Details, Code-Beispiele & Hersteller-Stellungnahme auf dev.to.
↗ Original-Artikel auf dev.to lesen
Wie bewertest du diesen Beitrag?
1 Klick Feedback
Teilen mit Netzwerk & Team:

Community-Analysen & Experten-Meinungen 0

Verfasse deine eigene Analyse, teile Workarounds oder diskutiere diesen Vorfall im Blog.
Noch keine Community-Analyse verfasst. Markiere einen Textabschnitt oder klicke oben auf Eigene Analyse verfassen“!
Community Pulse: Relevanz-Einschätzung
1 Klick Experten-Votum
🔴 Akute Relevanz 0%
🟡 In Evaluierung 0%
🟢 Keine Auswirkung 0%
Spannende Innovation 0%
Verwandte Story-Cluster & Quellen (Vektor-KI)
Port 8095 Engine
1 Quelle
Modify Windows Support Phone Number with PowerShell
1 Quelle
Die Zukunft des Einkaufens: Warum wir ein neues Kapitel aufschlagen (und wie du es mitschreiben kannst)
1 Quelle
ZDE Podcast 251: Wie sieht digitales Instore Marketing 2026 aus, Amit Chatterjee?
Ähnliche Beiträge
🔍 Verwandte News

Auch interessante Nachrichten Cutting Vercel Fluid CPU with Next.js Server-Side Caching

Thematisch verwandte Begriffe: Cutting, Vercel, Fluid, with · 6 Treffer

Laden...

Videos werden geladen ...

Laden...

Beiträge werden geladen ...

Laden...

Videos werden geladen ...

Laden...

Beiträge werden geladen ...

Laden...

Videos werden geladen ...

Laden...

Beiträge werden geladen ...

Laden...

Videos werden geladen ...

Laden...

Beiträge werden geladen ...

Laden...

Videos werden geladen ...