Så minskade vi våra kostnader för webbinfrastruktur med 80 % genom att flytta från Vercel till Cloudflare Workers och Railway

Vi flyttade vår webbplattform från Vercel till Cloudflare Workers och Railway och ersatte Next.js med en kombination av TanStack Router, TanStack Start och Hono, utifrån vad varje arbetsbelastning faktiskt behövde. Resultatet blev cirka 80 % lägre infrastrukturkostnader. Besparingen steg till omkring 90 % efter att vi börjat filtrera bort fientlig automatiserad trafik vid nätverkets kant. Det mesta av migreringen utfördes av AI-agenter som skrev kod, medan ingenjörerna fokuserade på arkitektur, krav och begränsningar, granskning och verifiering i produktionsmiljön.

23 september 2026

Quang Lam · Founder & CEO

Så minskade vi våra kostnader för webbinfrastruktur med 80 % genom att flytta från Vercel till Cloudflare Workers och Railway

I flera år var Vercel standardplattformen för nästan allt vi driftsatte på webben på WebCatalog. De flesta projekten använde Next.js, så kombinationen var naturlig. Våra marknadsföringssajter, produktgränssnitt, kontoinställningar, utvecklarkonsol, autentisering, administrationsverktyg och API:er hamnade alla på ungefär samma teknikstack.

Det fungerade bra länge. Vercel gjorde driftsättningar enkla, Next.js gav oss ett produktivt fullstack-ramverk, och vi behövde sällan tänka på infrastrukturen bakom dem.

Till slut passade den bekvämligheten inte längre våra produkters behov.

Våra marknadsföringssajter hade fortfarande nytta av SSR (serverrendering), men de flesta av våra andra webbappar hade det inte. De kunde vara vanliga SPA:er (enkelsidesapplikationer). Våra API:er behövde en vanlig Node.js-miljö med inbyggda beroenden och långlivade processer. Nästan allt annat i vår frontend-stack använde redan Vite. Samtidigt blev infrastrukturkostnaderna allt svårare att bortse från, särskilt när den publika och automatiserade trafiken ökade.

Till en början försökte vi optimera det vi redan hade. Vi övervägde att behålla Next.js och flytta det till Cloudflare Workers via en adapter. Vi provade Astro för marknadsföringssajterna. Vi körde också våra API:er på Cloudflare Containers under en kort period.

Till slut landade vi i något enklare: de flesta av våra webbappar använder nu Vite + TanStack Router på Cloudflare Workers, våra marknadsföringssajter använder TanStack Start med SSR på Cloudflare Workers, och våra API:er använder Hono + tRPC på Railway som långlivade Node.js-containrar.

Migreringen minskade våra kostnader för webbinfrastruktur med ungefär 80 %. När vi dessutom skärpte våra säkerhetsregler i Cloudflare och blockerade mer fientlig automatiserad trafik vid nätverkskanten ökade den totala besparingen till omkring 90 %.

Det mesta av migreringens implementationsarbete utfördes också av AI-kodningsagenter, främst Claude Fable 5 och Claude Opus 5. Ingenjörerna valde arkitektur, definierade begränsningar, granskade ändringar och verifierade resultatet.

Vi började inte med att lämna Vercel

Vår första instinkt var att optimera den befintliga lösningen.

webcatalog.io var den naturligaste utgångspunkten eftersom sajten får mycket publik trafik samtidigt som de flesta sidor ändras relativt sällan. Vi upptäckte att alltför mycket av sajten fortfarande renderades dynamiskt. Därför åtgärdade vi oavsiktlig dynamisk rendering, lade till ISR (inkrementell statisk regenerering) för välbesökta rutter, gjorde fler sidor möjliga att cachelagra och optimerade resurskrävande hantering av webbplatskartor.

Arbetet hjälpte, men gjorde också det underliggande problemet tydligare. Vi lade allt mer tid på att förstå varför relativt statiskt innehåll var dynamiskt, vilket beteende i ramverket som hade orsakat det och vilken funktion i ramverket vi behövde införa för att kunna cachelagra innehållet igen.

Samtidigt hade många av våra andra applikationer motsatt problem. Kontoinställningar, utvecklarkonsolen, administrationsappar och de flesta produktgränssnitt behövde ingen serverrendering alls. De var webbläsarapplikationer som kommunicerade med API:er.

Vid den punkten slutade frågan vara ”Hur minskar vi vår Vercel-faktura?” och blev i stället ”Vad skulle vi bygga om de här applikationerna inte redan var Next.js-applikationer?”

Vi övervägde Next.js på Cloudflare

Det minst omvälvande alternativet var att behålla Next.js och flytta det från Vercel till Cloudflare Workers.

Vi övervägde det på allvar eftersom Next.js kan köras på Cloudflare med hjälp av adapterlager. Då hade vi kunnat bevara stora delar av applikationernas befintliga struktur.

Men vi såg inte Next.js på Cloudflare som likvärdigt med Next.js på Vercel. Next.js är som mest integrerat med Vercels körmiljö, driftsättningssystem, cachebeteende och plattformsfunktioner. På Cloudflare måste en adapter översätta dessa förutsättningar till en annan körmiljö.

Det kan fungera bra, men om målet var att förenkla stacken kändes det inte optimalt att lägga till ännu ett kompatibilitetslager.

Det fanns också en bredare fråga om verktyg. Nästan allt annat vi byggde inom frontend använde redan Vite: skrivbordsapplikationer, webbläsartillägg, SPA:er och andra projekt på klientsidan.

Next.js hade i hög grad gått över till Turbopack, och Turbopack har förbättrats avsevärt. Det här handlade inte om prestanda. För oss var den större skillnaden ekosystemet. Vite var redan den gemensamma grunden för större delen av vår frontend-kodbas, med ett bredare ekosystem av insticksprogram och mer konfiguration som kunde återanvändas mellan projekt.

Att behålla Next.js på Cloudflare skulle alltså ha löst en del av hostingproblemet, men både skillnaden mellan ramverken och det separata ekosystemet för byggverktyg skulle ha funnits kvar.

Så vi tog ett steg tillbaka och tittade på vad varje typ av arbetslast faktiskt behövde.

Vi delade upp stacken efter arbetslast

När vi slutade leta efter en enda universell ersättare till Next.js blev arkitekturen mycket enklare.

Våra marknadsföringssajter behövde SSR eftersom de har publika, lokaliserade sidor, metadata, kanoniska webbadresser, webbplatskartor och trafik från sökmotorer.

De flesta av våra andra webbappar behövde inte SSR och kunde helt enkelt vara Vite-applikationer med TanStack Router.

Våra API:er behövde inte alls något React-ramverk och passade bättre i en vanlig Node.js-körmiljö.

Den slutliga uppdelningen såg ut så här:

Webbappar
Vite + TanStack Router
        │
        └── Cloudflare Workers

Marknadsföringssajter
TanStack Start + SSR
        │
        └── Cloudflare Workers

API:er
Hono + tRPC
        │
        └── Railway / Node.js-containrar

Principen blev enkel: använd SSR där det ger verkligt värde, använd en vanlig SPA där det inte gör det och kör backend-tjänster i en backend-körmiljö.

De flesta webbapparna blev SPA:er

SPA-migreringarna var den enklaste delen.

WebCatalogs webbapp flyttades särskilt snabbt: vi skapade grunden för ersättaren med Vite + TanStack Router, portade gränssnittet, flyttade driftsättningen till Cloudflare Workers och tog bort den gamla Next.js-versionen under samma förmiddag.

Vi upprepade samma mönster för Lexibirds webbapp, kontoinställningar, vår utvecklarkonsol, autentisering och administrationsappar. Från den första grundstrukturen för en SPA till att vi tog bort den sista Next.js-applikationen gick det ungefär 19 dagar.

För de här applikationerna är Cloudflare Workers avsiktligt okomplicerat. Vite bygger statiska filer, Cloudflare levererar dem och applikationsrutter faller tillbaka på index.html. Det finns ingen SSR-körmiljö eftersom ingenting behöver serverrenderas.

Det svårare var att bevara det beteende som hade vuxit fram kring applikationerna med tiden. Viss autentiseringslogik behövde flyttas från serverrutter i Next.js till API:et, och äldre versioner av WebCatalogs skrivbordsapp var fortfarande beroende av äldre slutpunkter som vi behövde hålla fungerande.

Att flytta React-gränssnittet var enkelt.

Att bevara kontrakten var svårare.

Vi provade Astro och tog bort det fem dagar senare

Marknadsföringssajterna var svårare.

Vårt första val var Astro, som verkade passa webcatalog.io och lexibird.com naturligt eftersom båda är publika, innehållstunga sajter och Astro fungerar bra med Cloudflare.

Vi började porta båda sajterna och avbröt fem dagar senare.

Det fanns inget enskilt avgörande fel. I stället samlades små brister i passformen på hög. Vissa rutter behövde databasåtkomst vid förrendering, medan vår byggmiljö avsiktligt saknade inloggningsuppgifter till produktionsdatabasen. React-öar gjorde gemensamt applikationstillstånd mindre naturligt. Vi stötte också på skillnader mellan förrenderade rutter och rutter som renderades vid körning, liksom vissa verktygsproblem i vårt kodförråd.

Inget av problemen var omöjligt att lösa. Det var just därför det var riskabelt att fortsätta. Vi hade lätt kunnat lägga ytterligare några veckor på att lösa det ena problemet efter det andra.

I stället tog vi bort implementationen och började om.

AI-agenter förändrade kalkylen bakom det beslutet. En stor del av det mekaniska portarbetet hade inte tagit veckor av ingenjörstid, så den nedlagda kostnaden var mindre och det var lättare att erkänna att vi föredrog en annan arkitektur.

TanStack Start passade bättre

Vi startade om migreringen av marknadsföringssajterna från den ursprungliga Next.js-koden, den här gången med TanStack Start.

Det passade mycket naturligare eftersom vi redan använde TanStack Router i SPA-applikationerna. Routning, loaders, sökparametrar och navigering byggde därför på liknande koncept. Koden förblev vanlig React och TypeScript, och byggsystemet var Vite.

Vi portade lexibird.com till TanStack Start på en dag. webcatalog.io följde därefter.

Fördelen var inte att TanStack Start magiskt löste alla problem. Det var att det passade den riktning som resten av vår stack redan var på väg mot.

I ett monorepo spelar det roll. Gemensamma byggverktyg innebär fler återanvändbara insticksprogram och konfigurationer, färre specialfall vid felsökning, mindre kontextväxling för utvecklarna och färre projektspecifika konventioner för kodningsagenterna att upptäcka.

Cloudflare var mycket billigare för vår trafik

Arkitekturen var bara en del av förklaringen till att vår faktura minskade. Cloudflares prissättning var en viktig faktor, särskilt för bandbredd.

Cloudflare Workers Paid tar i dagsläget huvudsakligen betalt för anrop och CPU-användning och lägger inte på några avgifter för dataöverföring eller bandbredd för Workers. (developers.cloudflare.com) Det spelar stor roll för publika webbplatser, eftersom ett anrop kan använda väldigt lite CPU men ändå överföra HTML, JavaScript, bilder, typsnitt och andra filer.

Vercels prismodell omfattar också användningskategorier och inkluderade volymer kopplade till nätverket, bland annat Fast Data Transfer och Fast Origin Transfer. (vercel.com) För vår trafikprofil var Cloudflare betydligt mer ekonomiskt fördelaktigt.

Besparingarna berodde inte bara på att vi bytte leverantör. Vi flyttade också många applikationer till statiska Vite-byggen, minskade onödig SSR, gjorde cachelagringen tydligare och flyttade API-arbetslaster till en körmiljö som passade dem bättre. Men Cloudflares prissättning, särskilt för bandbredd, bidrog starkt till den minskning på ungefär 80 % som vi såg.

Den siffran gäller vår specifika arbetslast. Vi påstår inte att alla applikationer som flyttar från Vercel till Cloudflare kommer att spara 80 %.

API:erna hamnade på Railway

API:erna var ett separat problem.

Trots att de var Next.js-projekt var de redan till största delen oberoende av Next.js. WebCatalogs API omfattade ungefär 34 000 kodrader, men bara sju filer importerade next/server. tRPC använde redan sin Fetch-adapter, och Inngest hade stöd för Hono.

Vi ersatte HTTP-skalet i Next.js med Hono. Den delen var förvånansvärt liten.

Den svårare frågan var var det skulle köras. Vanliga Workers passade inte bra eftersom API:erna använder Node.js och inbyggda beroenden som sharp.

Vi provade först Cloudflare Containers, vilket gjorde att vi snabbt kunde lämna Vercel. Men efter att ha kört lösningen i produktion märkte vi att den krävde mer manuell kapacitetsjustering än vi ville ägna oss åt då.

Så vi flyttade API:erna igen.

I dag körs de på Railway som vanliga, långlivade Node.js-containertjänster. CI (kontinuerlig integrering) bygger Docker-avbilder, skickar dem till vårt register och Railway sköter horisontell autoskalning.

Allt behöver inte köras vid nätverkskanten.

Att lämna Vercel innebar mer eget ansvar

Den lägre kostnaden hade en baksida.

Vercel och Next.js hade hanterat många infrastrukturfunktioner på en högre nivå. Med TanStack Start och Workers gick vi i stället mot uttrycklig HTTP-cachelagring. En sida renderas, vi skickar tillbaka cacheheaders och Cloudflare cachelagrar svaret. Cachelagring i webbläsaren och vid nätverkskanten kan ha olika regler, inklusive stale-while-revalidate vid nätverkskanten.

Vi uppskattade att besluten blev uttryckliga, men när man själv styr infrastrukturen blir misstagen också ens egna.

Vi gjorde några sådana misstag. En cacheregel i produktion råkade matcha besökarspecifika svar från TanStacks serverfunktioner, och en annan cachekonfiguration samverkade illa med SPA:ns fallback-beteende. De buggarna påminde oss om att man inte kan bevisa att en migrering är korrekt enbart genom att granska kodförrådet. Produktionsinfrastrukturen är också en del av systemet.

AI-agenter förändrade hur vi migrerade

Det mesta av implementationsarbetet utfördes av kodningsagenter, främst Claude Fable 5 och Claude Opus 5.

Ramverksmigreringar passar ovanligt bra för agenter eftersom mycket av arbetet har en tydlig befintlig referens. Flytta den här rutten, bevara den här webbadressen, ersätt det här ramverks-API:et, behåll samma metadata, kör typkontroll, rätta felen och jämför resultatet med den gamla implementationen.

För webcatalog.io hade vi en migreringsplan som delade upp arbetet i steg som grundstruktur, produktsidor, katalogsidor, sökning, blogg, prissättning, omdirigeringar, webbplatskartor och övergång till den nya lösningen. I stället för att be en agent att ”migrera webcatalog.io till TanStack Start” gav vi den avgränsade uppgifter med uttryckliga krav på vad som måste förbli oförändrat.

Den befintliga applikationen blev specifikationen. Agentens uppgift var att återskapa beteendet med den nya arkitekturen, inte att uppfinna produkten på nytt.

Det flyttade människornas arbete från att manuellt översätta kod till frågor som: Behöver den här sidan verkligen SSR? Vilket beteende är avsiktligt? Vad får cachelagras globalt? Vilka webbadresser måste förbli identiska? Var ska autentiseringen ske? När bör vi sluta försöka få en viss lösning att fungera?

Vi granskade fortfarande resultatet, körde byggen och typkontroller och verifierade manuellt mer riskfyllda områden som autentisering, SEO (sökmotoroptimering), omdirigeringar och cachelagring.

Den viktiga förändringen var inte att AI skrev kod åt oss. Det var att AI gjorde det billigare att experimentera.

Det blev mycket lättare att motivera att prova Astro och ta bort det efter fem dagar. Det blev mindre smärtsamt att flytta API:erna en gång och sedan konstatera att en annan plattform passade bättre. Det mekaniska arbetet kostade mindre, så vi kunde byta riktning när arkitekturen var fel i stället för att fortsätta bara för att vi redan hade investerat så mycket i den.

Agenter gjorde implementationskapacitet mindre till en bristvara.

Det gjorde arkitektur, begränsningar, granskning och verifiering viktigare.

80 % blev ungefär 90 %

Efter migreringen var våra kostnader för webbinfrastruktur ungefär 80 % lägre.

Sedan började vi uppmärksamma vilka anrop som över huvud taget nådde applikationerna.

En betydande del av trafiken på det publika internet är automatiserad: sökmotorer, AI-crawlrar, agenter, skrapare, skannrar och mindre välvilliga botar. En del av den trafiken är användbar och en del är det inte.

Med applikationerna direkt bakom Cloudflare skärpte vi våra säkerhetsregler så att fientlig automatiserad trafik kunde stoppas vid nätverkskanten innan den utlöste arbete i applikationerna eller databasen.

Efter det nådde våra totala besparingar ungefär 90 % jämfört med den gamla lösningen.

Den slutliga minskningen kom av flera samverkande faktorer: Cloudflares lägre priser, särskilt för bandbredd; mindre arbete på serversidan; en bättre körmiljö för våra API:er; tydligare cachelagring; och färre onödiga anrop som över huvud taget nådde applikationerna.

Där vi landade

Det finns inga Next.js-applikationer kvar i vårt kodförråd. De flesta av våra webbappar är nu SPA:er med Vite + TanStack Router på Cloudflare Workers. webcatalog.io och lexibird.com använder TanStack Start på Cloudflare Workers eftersom de sajterna verkligen har nytta av SSR. Våra API:er använder Hono + tRPC på Railway och körs som vanliga Node.js-containrar. Nästan alla våra frontend-projekt ingår nu i Vite-ekosystemet.

Våra infrastrukturkostnader sjönk med ungefär 80 %, och Cloudflares betydligt fördelaktigare prissättning för vår trafik, särskilt bandbredd, bidrog starkt. Att filtrera bort fientlig automatiserad trafik vid nätverkskanten ökade den totala besparingen till omkring 90 %.

Men det resultat vi värdesätter mest är arkitektoniskt. Marknadsföringssajter får SSR, allt annat som kan vara en SPA är en SPA, och API:er körs på riktiga servrar när riktiga servrar är enklare.

Vi började med att försöka göra Vercel billigare.

Vi slutade med insikten att vi inte behövde större delen av den arkitektur vi betalade för.