Как преместването от Vercel към Cloudflare Workers + Railway намали разходите ни за уеб инфраструктура с 80%

Мигрирахме уеб стека си от Vercel към Cloudflare Workers и Railway, като заменихме Next.js с комбинация от TanStack Router, TanStack Start и Hono според нуждите на всяко конкретно натоварване. В резултат разходите за инфраструктура намаляха с около 80%, а след филтриране на злонамерения автоматизиран трафик на периферно ниво — с около 90%. По-голямата част от работата по миграцията беше извършена от AI агенти за програмиране, докато инженерите се съсредоточиха върху архитектурата, ограниченията, прегледа и проверката в продукционна среда.

23 септември 2026 г.

Quang Lam · Founder & CEO

Как преместването от Vercel към Cloudflare Workers + Railway намали разходите ни за уеб инфраструктура с 80%

В продължение на години Vercel беше платформата, на която по подразбиране разполагахме почти всичко уеб базирано в WebCatalog. Повечето от тези проекти използваха Next.js, така че комбинацията беше естествена. Маркетинговите ни сайтове, продуктовите интерфейси, настройките на акаунтите, конзолата за разработчици, удостоверяването, административните инструменти и API интерфейсите — всичко се оказа изградено върху приблизително един и същ технологичен стек.

Дълго време това работеше добре. Vercel улесняваше разполагането на приложенията, Next.js ни даваше продуктивна рамка за разработка както на фронтенд, така и на бекенд, а ние рядко трябваше да мислим за инфраструктурата под тях.

С времето обаче това удобство престана да отговаря на нуждите на продуктите ни.

Маркетинговите ни сайтове все още печелеха от SSR (рендериране от страна на сървъра), но повечето от останалите ни уеб приложения нямаха нужда от него. Те можеха да бъдат обикновени SPA (едностранични приложения). API интерфейсите ни се нуждаеха от стандартна Node.js среда с нативни зависимости и дълготрайни процеси. Почти всичко останало във фронтенд стека ни вече използваше Vite. Същевременно разходите за инфраструктура ставаха все по-трудни за пренебрегване, особено с нарастването на публичния и автоматизирания трафик.

Първоначално се опитахме да оптимизираме съществуващата конфигурация. Обмислихме да запазим Next.js и да го преместим в Cloudflare Workers чрез адаптер. Изпробвахме Astro за маркетинговите сайтове. За кратко разположихме API интерфейсите си в Cloudflare Containers.

В крайна сметка стигнахме до по-просто решение: повечето ни уеб приложения вече използват Vite + TanStack Router в Cloudflare Workers, маркетинговите ни сайтове използват TanStack Start със SSR в Cloudflare Workers, а API интерфейсите ни използват Hono + tRPC в Railway като дълготрайни Node.js контейнери.

Миграцията намали разходите ни за уеб инфраструктура с приблизително 80%. След като затегнахме и правилата за сигурност в Cloudflare и започнахме да блокираме повече злонамерен автоматизиран трафик на периферията на мрежата, общите спестявания нараснаха до около 90%.

По-голямата част от реализацията на миграцията също беше извършена от AI агенти за програмиране, основно Claude Fable 5 и Claude Opus 5, докато инженерите определяха архитектурата и ограниченията, преглеждаха промените и проверяваха резултата.

Не започнахме с напускане на Vercel

Първият ни инстинкт беше да оптимизираме съществуващата конфигурация.

webcatalog.io беше най-очевидното място, от което да започнем, защото получава много публичен трафик, а повечето му страници се променят сравнително рядко. Установихме, че твърде голяма част от сайта все още се рендерира динамично, затова премахнахме неволното динамично рендериране, добавихме ISR (инкрементално статично регенериране) към маршрутите с голям трафик, направихме повече страници подходящи за кеширане и оптимизирахме скъпоструващата обработка на картите на сайта.

Тази работа помогна, но и направи основния проблем по-ясен. Отделяхме все повече време, за да разберем защо сравнително статично съдържание се рендерира динамично, кое поведение на рамката го е причинило и кой механизъм на рамката трябва да приложим, за да може то отново да се кешира.

Междувременно много от другите ни приложения имаха обратния проблем. Настройките на акаунтите, конзолата за разработчици, административните приложения и повечето продуктови интерфейси изобщо не се нуждаеха от рендериране на сървъра. Те бяха приложения в браузъра, които комуникират с API интерфейси.

В този момент въпросът престана да бъде „Как да намалим сметката си за Vercel?“ и стана „Какво бихме изградили, ако тези приложения вече не бяха написани с Next.js?“

Обмислихме Next.js в Cloudflare

Вариантът с най-малко промени беше да запазим Next.js и да го преместим от Vercel в Cloudflare Workers.

Разгледахме сериозно тази възможност, защото Next.js може да работи в Cloudflare чрез адаптерни слоеве, което би ни позволило да запазим голяма част от съществуващата структура на приложенията.

Но не смятахме, че Next.js в Cloudflare е равностоен на Next.js във Vercel. Next.js е най-тясно интегриран със средата за изпълнение, системата за разполагане, поведението на кеша и възможностите на платформата Vercel. В Cloudflare адаптерът трябва да пренесе тези допускания върху различна среда за изпълнение.

Това може да работи добре, но ако целта ни беше да опростим стека, добавянето на още един слой за съвместимост не изглеждаше идеално.

Имаше и по-общ въпрос, свързан с инструментите. Почти всичко останало, което разработвахме за фронтенда, вече използваше Vite: настолни приложения, разширения за браузъри, SPA и други проекти, изпълнявани от страна на клиента.

Next.js беше насочил развитието си силно към Turbopack, а Turbopack се подобри значително. Това не беше оплакване от производителността. За нас по-важната разлика беше екосистемата. Vite вече беше общата основа за по-голямата част от фронтенд кода ни, с по-широка екосистема от плъгини и повече конфигурация, която можехме да използваме повторно в различни проекти.

Следователно запазването на Next.js в Cloudflare щеше да реши част от проблема с хостинга, но щеше да запази както несъответствието между рамките, така и отделна екосистема от инструменти за изграждане.

Затова направихме крачка назад и разгледахме от какво всъщност се нуждае всеки тип натоварване.

Разделихме стека според натоварването

Щом престанахме да търсим един универсален заместител на Next.js, архитектурата стана много по-проста.

Маркетинговите ни сайтове се нуждаеха от SSR, защото имат публични, локализирани страници, метаданни, канонични URL адреси, карти на сайта и трафик от търсачки.

Повечето от останалите ни уеб приложения нямаха нужда от SSR и можеха просто да бъдат приложения с Vite и TanStack Router.

API интерфейсите ни изобщо не се нуждаеха от React рамка и бяха по-подходящи за стандартна Node.js среда за изпълнение.

Окончателното разделение изглеждаше така:

Уеб приложения
Vite + TanStack Router
        │
        └── Cloudflare Workers

Маркетингови сайтове
TanStack Start + SSR
        │
        └── Cloudflare Workers

API интерфейси
Hono + tRPC
        │
        └── Railway / Node.js контейнери

Правилото стана просто: използвайте SSR там, където носи реална стойност, обикновено SPA там, където не носи, и изпълнявайте бекенд услугите в среда, подходяща за бекенд.

Повечето уеб приложения станаха SPA

Миграциите към SPA бяха най-лесната част.

Уеб приложението на WebCatalog беше преместено особено бързо: създадохме основата на заместителя с Vite + TanStack Router, пренесохме интерфейса, прехвърлихме разполагането към Cloudflare Workers и премахнахме старата версия с Next.js — всичко това в рамките на една сутрин.

Повторихме същия подход за уеб приложението Lexibird, настройките на акаунтите, конзолата ни за разработчици, удостоверяването и административните приложения. От създаването на основата на първото SPA до изтриването на последното приложение с Next.js минаха около 19 дни.

За тези приложения Cloudflare Workers умишлено върши съвсем обикновена работа. Vite изгражда статичните файлове, Cloudflare ги обслужва, а маршрутите на приложението използват index.html като резервен вариант. Няма среда за SSR, защото няма нищо, което да се нуждае от рендериране на сървъра.

По-трудната част беше да запазим поведението, натрупано около тези приложения с времето. Част от логиката за удостоверяване трябваше да се премести от сървърните маршрути на Next.js в API, а по-старите версии на настолното приложение WebCatalog все още зависеха от стари крайни точки, които трябваше да продължат да работят.

Преместването на React интерфейса беше лесно.

Запазването на съществуващите интерфейсни договори беше по-трудно.

Изпробвахме Astro и го изтрихме пет дни по-късно

Маркетинговите сайтове бяха по-трудни.

Първият ни избор беше Astro, който изглеждаше естествено решение за webcatalog.io и lexibird.com, защото и двата са публични сайтове с много съдържание, а Astro се интегрира добре с Cloudflare.

Започнахме да пренасяме и двата сайта, а пет дни по-късно спряхме.

Нямаше един-единствен фатален недостатък. Вместо това се натрупваха дребни несъответствия. Някои маршрути се нуждаеха от достъп до базата данни при предварителното рендериране, докато средата ни за изграждане умишлено нямаше данни за достъп до продукционната база. React островите правеха споделеното състояние на приложението по-неестествено. Сблъскахме се и с разлики между предварително рендерираните маршрути и тези, рендерирани по време на изпълнение, както и с известно триене при инструментите в хранилището ни.

Нито един от тези проблеми не беше невъзможен за решаване. Точно затова продължаването беше опасно. Лесно можехме да прекараме още няколко седмици в решаване на проблем след проблем.

Вместо това изтрихме реализацията и започнахме отново.

AI агентите промениха икономиката на това решение. Голяма част от механичното пренасяне не беше отнела седмици инженерно време, така че вече направената невъзвръщаема инвестиция беше по-малка и беше по-лесно да признаем, че предпочитаме друга архитектура.

TanStack Start се вписа по-добре

Започнахме миграцията на маркетинговите сайтове отначало, като този път тръгнахме от оригиналния код с Next.js и използвахме TanStack Start.

Той се вписа много по-естествено, защото вече използвахме TanStack Router в SPA приложенията. Така маршрутизирането, зареждащите функции, параметрите за търсене и навигацията следваха сходни принципи. Кодът си остана обикновен React и TypeScript, а системата за изграждане беше Vite.

Пренесохме lexibird.com към TanStack Start за един ден. След него дойде ред и на webcatalog.io.

Предимството не беше, че TanStack Start решаваше магически всеки проблем. То беше, че се вписваше в посоката, в която вече се развиваше останалата част от стека ни.

При едно монорепозитори това има значение. Споделените инструменти за изграждане означават повече плъгини и конфигурации за повторно използване, по-малко специални случаи при отстраняване на грешки, по-малко превключване между различни контексти за разработчиците и по-малко специфични за отделните проекти правила, които агентите за програмиране трябва да откриват.

Cloudflare беше много по-евтин за нашия трафик

Архитектурата беше само част от причината сметката ни да намалее. Ценообразуването на Cloudflare беше основен фактор, особено по отношение на преноса на данни.

Платеният план Cloudflare Workers в момента таксува основно според броя на заявките и използването на процесорно време и не начислява допълнителни такси за пренос на данни или мрежов трафик при Workers. (developers.cloudflare.com) Това има голямо значение за публичните уебсайтове, защото една заявка може да използва много малко процесорно време, но въпреки това да прехвърля HTML, JavaScript, изображения, шрифтове и други файлове.

Ценовият модел на Vercel включва и категории и лимити, свързани с мрежовото потребление, сред които Fast Data Transfer и Fast Origin Transfer. (vercel.com) За нашия профил на трафик Cloudflare беше значително по-изгоден.

Спестяванията не дойдоха само от смяната на доставчика. Преминахме и към статични компилации с Vite за много приложения, намалихме ненужния SSR, направихме кеширането по-явно и преместихме API натоварването в по-подходяща среда за изпълнение. Но ценообразуването на Cloudflare, особено по отношение на преноса на данни, имаше голям принос за наблюдаваното от нас намаление от приблизително 80%.

Това число се отнася конкретно за нашето натоварване. Не твърдим, че всяко приложение, преместено от Vercel в Cloudflare, ще спести 80%.

API интерфейсите се озоваха в Railway

API интерфейсите бяха отделен проблем.

Макар да бяха проекти с Next.js, те вече бяха до голяма степен независими от него. API интерфейсът на WebCatalog съдържаше приблизително 34 000 реда код, но само седем файла импортираха next/server. tRPC вече използваше своя Fetch адаптер, а Inngest поддържаше Hono.

Заменихме HTTP обвивката на Next.js с Hono. Тази част се оказа изненадващо малка.

По-трудният въпрос беше къде да го изпълняваме. Обикновените Workers не бяха подходящи, защото API интерфейсите използват Node.js и нативни зависимости като sharp.

Първоначално изпробвахме Cloudflare Containers, което ни позволи бързо да се отделим от Vercel. Но след като използвахме тази конфигурация в продукционна среда, установихме, че оперативният ѝ модел изисква повече ръчно настройване на капацитета, отколкото искахме тогава.

Затова преместихме API интерфейсите отново.

Днес те работят в Railway като обикновени дълготрайни Node.js услуги в контейнери. CI (непрекъсната интеграция) изгражда Docker образите, качва ги в нашия регистър, а Railway се грижи за хоризонталното автоматично мащабиране.

Не всичко трябва да работи на периферията на мрежата.

Напускането на Vercel означаваше да поемем повече отговорност

По-ниската цена дойде с компромис.

Vercel и Next.js бяха управлявали много аспекти на инфраструктурата на по-високо ниво. С TanStack Start и Workers вместо това преминахме към изрично HTTP кеширане. Страницата се рендерира, връщаме HTTP заглавки за кеширане и Cloudflare кешира отговора. Кеширането в браузъра и на периферията на мрежата може да следва различни правила, включително поведение stale-while-revalidate на периферията.

Харесваше ни, че тези решения станаха изрични, но когато инфраструктурата е под ваш пряк контрол, грешките също са ваша отговорност.

Допуснахме няколко. Едно правило за кеширане в продукционна среда неволно обхвана отговори на сървърни функции на TanStack, специфични за отделни посетители, а друга конфигурация на кеша взаимодействаше зле с резервното маршрутизиране на SPA. Тези грешки ни напомниха, че коректността на миграцията не може да се докаже само въз основа на хранилището с код. Продукционната инфраструктура също е част от системата.

AI агентите промениха начина, по който мигрирахме

По-голямата част от работата по реализацията беше извършена от агенти за програмиране, основно Claude Fable 5 и Claude Opus 5.

Миграциите между рамки са особено подходящи за агенти, защото за голяма част от работата има ясна съществуваща отправна точка. Премести този маршрут, запази този URL адрес, замени този API на рамката, запази същите метаданни, изпълни проверката на типовете, поправи грешките и сравни резултата със старата реализация.

За webcatalog.io поддържахме план за проследяване на миграцията, който разделяше работата на етапи като основа, продуктови страници, страници от каталога, търсене, блог, цени, пренасочвания, карти на сайта и окончателно преминаване. Вместо да кажем на агент „мигрирай webcatalog.io към TanStack Start“, му възлагахме ограничени по обхват задачи с изрично посочени изисквания, които не бива да се нарушават.

Съществуващото приложение се превърна в спецификацията. Задачата на агента беше да възпроизведе поведението с новата архитектура, а не да преоткрие продукта.

Това измести човешките усилия от ръчното пренасяне на код към въпроси като: Тази страница наистина ли трябва да използва SSR? Кое поведение е умишлено? Какво може да се кешира глобално? Кои URL адреси трябва да останат непроменени? Къде трябва да се извършва удостоверяването? Кога трябва да спрем да се опитваме да накараме даден подход да работи?

Продължихме да преглеждаме резултатите, да изпълняваме компилации и проверки на типовете и ръчно да проверяваме областите с по-висок риск като удостоверяване, SEO (оптимизация за търсачки), пренасочвания и кеширане.

Важната промяна не беше, че AI пишеше код вместо нас. Важното беше, че AI направи експериментирането по-евтино.

Стана много по-лесно да оправдаем изпробването на Astro и изтриването на реализацията пет дни по-късно. Преместването на API интерфейсите веднъж и последвалото решение, че друга платформа е по-подходяща, беше по-малко болезнено. Механичната работа беше по-евтина, така че можехме да сменим посоката, когато архитектурата се окажеше неподходяща, вместо да продължаваме само защото вече сме вложили твърде много в нея.

Агентите направиха капацитета за реализация по-малко ограничен ресурс.

Това направи архитектурата, ограниченията, прегледа и проверката още по-важни.

80% станаха приблизително 90%

След миграцията разходите ни за уеб инфраструктура бяха приблизително 80% по-ниски.

След това започнахме да обръщаме повече внимание на това кои заявки изобщо достигат до приложенията.

Значителна част от публичния интернет трафик е автоматизирана: търсачки, AI роботи за обхождане, агенти, инструменти за извличане на данни, скенери и не толкова добронамерени ботове. Част от този трафик е полезен, а друга — не.

Тъй като приложенията вече бяха непосредствено зад Cloudflare, затегнахме правилата си за сигурност, така че злонамереният автоматизиран трафик да бъде отхвърлян на периферията на мрежата, преди да задейства обработка в приложенията или работа с базата данни.

След това общите ни спестявания достигнаха приблизително 90% в сравнение със старата конфигурация.

Крайното намаление се дължеше на съчетанието от няколко фактора: по-ниските цени на Cloudflare, особено за пренос на данни; по-малко работа от страна на сървъра; по-подходяща среда за изпълнение на API интерфейсите ни; по-ясно зададено кеширане; и по-малко ненужни заявки, които изобщо достигат до приложенията.

До какво решение стигнахме

В хранилището ни вече няма приложения с Next.js. Повечето ни уеб приложения вече са SPA с Vite + TanStack Router в Cloudflare Workers. webcatalog.io и lexibird.com използват TanStack Start в Cloudflare Workers, защото тези сайтове действително печелят от SSR. API интерфейсите ни използват Hono + tRPC в Railway, изпълнявани като обикновени Node.js контейнери. Почти всички наши фронтенд проекти вече са в екосистемата на Vite.

Разходите ни за инфраструктура спаднаха с приблизително 80%, като значително по-изгодните цени на Cloudflare за нашия трафик, особено за пренос на данни, допринесоха много за това. Филтрирането на злонамерения автоматизиран трафик на периферията на мрежата увеличи общите спестявания до около 90%.

Но резултатът, който ценим най-много, е архитектурният. Маркетинговите сайтове получават SSR, всичко останало, което може да бъде SPA, е SPA, а API интерфейсите работят на истински сървъри, когато това е по-простото решение.

Започнахме с опит да намалим разходите си за Vercel.

Накрая осъзнахме, че не се нуждаем от по-голямата част от архитектурата, за която плащахме.