prodejní pitch se rozpadne rychle
Edge Functions se prodávají přes dost specifický typ benchmarkového poblouznění: někdo ukáže request odbavený za 12 ms z POPu blízko uživatele, všichni spokojeně kývnou, a o šest týdnů později se tým snaží nacpat skutečný backend do prostředí, které vzniklo pro lehké tvarování requestů, ne pro ošklivou, stavovou logiku citlivou na CPU, která ve skutečnosti drží produkt při životě.
Problém začíná už u runtime. V Next.js 14 na Vercelu je Edge Runtime v zásadě omezený V8 isolate s Web API, ne plnohodnotný Node.js proces. V praxi to znamená žádná nativní Node API v běžném smyslu, omezenou kompatibilitu balíčků a dlouhý ocas knihoven, které buď spadnou při buildu, nebo hůř, projdou CI a pak vybuchnou až za běhu s chybami jako The edge runtime does not support Node.js 'crypto' module nebo Dynamic Code Evaluation (e.g. 'eval', 'new Function') not allowed in Edge Runtime. Pokud vaše appka dělá parsování dokumentů, manipulaci s obrázky, generování PDF, exporty do Excelu, migraci hesel přes bcrypt, S3 multipart upload přes dospělé SDK cesty nebo cokoliv, co sahá na nativní moduly, místo shippingu produktu začnete smlouvat s runtime.
U přístupu do databáze se tahle představa sesype úplně. Klasické PostgreSQL drivery jako pg počítají s dlouho žijícími TCP spojeními. Edge runtime vám tenhle typ síťování prostě nedá. Skončíte u HTTP databázových proxy, serverless driverů nebo vendor-specific adaptérů, a každý z nich přidá další vrstvu latence, další limit a další způsob, jak se to může rozbít. Na jednoduchý key lookup to stačí. Jakmile do hry vstoupí transakce, advisory locky, session state nebo složitější chování ORM, začne se to třást.
Ve Steezru jsme to viděli na vlastní oči u SaaS backendů, kde frontend tým chtěl na edge dělat auth checky a tenant resolution, což dávalo smysl. Pak se scope začal rozjíždět: do stejné cesty se přesunulo generování faktur, potom CRM sync logika, potom audit zápisy. Deployment zůstal rychlý. Systém se zhoršil.
kde edge opravdu funguje
Edge je výborný na úzkou sadu úloh, a právě tahle úzkost je výhoda, pokud ji respektujete. Request routing, redirecty podle geolokace, filtrování botů, kontrola cookies, normalizace cache key, lehké auth gating, přiřazování do AB testů a doručování stale obsahu do toho prostředí sedí dobře, protože jsou většinou bezstavové, většinou levné a snesou omezení prostředí.
Typický příklad je Next.js middleware. Můžete zkontrolovat session cookie, ověřit kompaktní JWT přes jose, přidat tenant metadata do headers a přepsat /app na /eu/app nebo /us/app podle profilu uživatele nebo regionu POPu, to všechno ještě předtím, než request sáhne na regionální compute. Funguje to dobře, protože logika zůstává malá a deterministická. Middleware soubor jako tenhle je nudný, a přesně to chcete:
1// middleware.ts2import { NextRequest, NextResponse } from 'next/server'3import { jwtVerify } from 'jose'45export async function middleware(req: NextRequest) {6 const token = req.cookies.get('session')?.value7 if (!token) return NextResponse.redirect(new URL('/login', req.url))89 const secret = new TextEncoder().encode(process.env.JWT_SECRET)10 const { payload } = await jwtVerify(token, secret)11 const region = payload.region === 'us' ? 'us' : 'eu'1213 const headers = new Headers(req.headers)14 headers.set('x-tenant-id', String(payload.tenant_id))15 headers.set('x-home-region', region)1617 return NextResponse.next({ request: { headers } })18}1920export const config = {21 matcher: ['/app/:path*']22}
Takový request pak může skončit na regionálním API ve Frankfurtu nebo Ashburnu, kde žije skutečná logika, kde se PostgreSQL spojení chovají normálně, kde můžete pustit Prisma, psycopg, ffmpeg, LibreOffice nebo headless browser bez modlení, že bundle compiler neodstraní něco důležitého.
Sem patří i caching. Veřejné produktové stránky, redirecty na podepsané assety, bootstrap payloady pro feature flagy a předpočítané dashboard shelly umí z POP-local doručení těžit hodně. Edge cestu držte pokud možno bez side effectů. Ve chvíli, kdy request potřebuje transakční správnost, víc CPU nebo širokou kompatibilitu knihoven, pošlete ho domů do regionu, který máte pod kontrolou a kterému rozumíte.
db spojení, cpu limity a křehký kód
Seniorní inženýři se většinou nespálí na hello-world ukázce. Spálí se na dopadech druhého řádu, na těch divných provozních nákladech, které se objeví až ve chvíli, kdy je provoz nerovnoměrný a produktové požadavky přestanou být hodné.
První je konektivita do databáze. Prisma na edge se zlepšila díky adaptérům a Data Proxy stylu přístupu, a na trhu jsou v tomhle směru slušné produkty. Ergonomie ale pořád zaostává za obyčejnou regionální Node službou, která mluví s PostgreSQL přes normální connection pool. Transakce přes více query jsou pomalejší a hůř se trasují, sémantika spojení se liší podle vendora a některá ORM v edge-compatible režimech potichu vypínají funkce. Jestli jste někdy museli vysvětlovat, proč jeden endpoint používá @prisma/client, druhý fetch-based adaptér a třetí ORM obchází úplně kvůli limitu driveru, už víte, že ty náklady nejsou teoretické.
Pak přijdou CPU limity. Edge runtime je navržený na krátké bursty. Zní to neškodně, dokud váš údajně jednoduchý endpoint časem nenabere trochu práce navíc, třeba HMAC verifikaci nad velkým tělem webhooku, merge tenant konfigurace, rozbalení permission graphu nebo validaci přes zod nad payloadem velkým jako kratší román. Medián requestu pořád vypadá dobře, p95 začne lézt nahoru, a pak dostanete timeout šum, který nikdo neumí lokálně reprodukovat, protože next dev na MacBooku fakt není dobrá simulace omezeného isolate běžícího na druhé straně planety.
Křehčí jsou i deploymenty. Týmy začnou auditovat každou dependency kvůli edge kompatibilitě, pinovat verze, aby obešly regrese, udržovat oddělené code paths pro runtime = 'edge' a runtime = 'nodejs', a číst zdrojáky balíčků jen proto, aby zjistily, proč transitivní import přitáhl fs. Častý fail v Next.js buildu vypadá takhle:
1Module not found: Can't resolve 'net'2Import trace for requested module:3./node_modules/pg/lib/connection.js4./node_modules/pg/lib/index.js5./src/lib/db.ts
V tu chvíli už nearchitektujete systém, ale obcházíte chování bundleru. To je špatná ekonomika inženýringu. Volba infrastruktury má codebase zjednodušit, ne hnát každou feature přes síto kompatibility.
hybridní model, který drží
Model, který doporučuju, je jednoduchý: edge pro přijetí requestu a zrychlení response, regionální compute pro business logiku a mutace dat. Můžete to provozovat na Vercelu, Fly.io, obyčejném Kubernetes nebo na nudné sadě VM. Princip zůstává stejný.
Na Vercelu s Next.js nechte middleware.ts na edge. Route Handlers používejte selektivně. Veřejné cachovatelné endpointy můžou zůstat edge-native, pokud jen skládají data z headers, cookies, feature flagů nebo KV cache. Stavové API routy by měly Node deklarovat explicitně:
1// app/api/orders/route.ts2export const runtime = 'nodejs'3export const preferredRegion = 'fra1'45import { NextRequest, NextResponse } from 'next/server'6import { prisma } from '@/lib/prisma'78export async function POST(req: NextRequest) {9 const body = await req.json()1011 const order = await prisma.order.create({12 data: {13 customerId: body.customerId,14 totalCents: body.totalCents15 }16 })1718 return NextResponse.json(order, { status: 201 })19}
Ten jeden řádek, runtime = 'nodejs', ušetří hodně bolesti. Přidejte preferredRegion, pokud databáze žije na jednom místě a správnost je důležitější než oholit 40 ms u requestu, který něco mutuje.
Na Fly.io může být to rozdělení ještě čistší. Dejte Next.js blízko uživatelům kvůli shellu a cachovatelným responsím, a zápisy i těžší ready pošlete do regionální Django nebo Node služby připnuté blízko Postgresu. fly.toml pro backend může vypadat třeba takhle:
1app = "crm-api"2primary_region = "fra"34[http_service]5 internal_port = 80806 force_https = true7 auto_stop_machines = true8 auto_start_machines = true9 min_machines_running = 11011[[vm]]12 cpu_kind = "shared"13 cpus = 214 memory_mb = 1024
Tím získáte stabilní domov pro dlouho běžící DB spojení, background joby a nativní dependency. Mezitím edge vrstva řeší fast-path věci. Přesně tenhle tvar jsme používali na zákaznických portálech i systémech typu ERP, včetně stacků s Next.js vpředu a Django vzadu, protože schvalování faktur a document processing pipeline nejsou jednodušší jen proto, že existuje edge runtime.
observabilita, nebo střílení od boku
Hybridní setup funguje jen tehdy, když tracing čistě přechází přes hranici obou vrstev. Jinak se z edge vrstvy stane továrna na fámy o latenci, všichni budou vinit špatný hop a incident review se změní v lidovou slovesnost.
Začněte request ID vygenerovaným na prvním vstupním bodě, typicky v middleware. Pošlete ho dál přes všechny interní volání v headers jako x-request-id, x-tenant-id a traceparent, pokud jedete na OpenTelemetry. Logujte edge rozhodnutí explicitně: cache hit nebo miss, výsledek auth, zvolený region, cíl rewrite a jestli byl request short-circuited. Pak logujte stejné request ID i v regionální službě spolu s DB timingy.
V Next.js můžete OTel zapojit přes instrumentation.ts, exportovat traces do OTLP collectoru a pak je sledovat v Grafana Tempo, Datadogu nebo Honeycombu. Na debugging request path mám rád Honeycomb, protože high-cardinality pole bere jako first-class věc, a hybridní systémy z definice generují spoustu high-cardinality kontextu. Užitečná sada spanů vypadá třeba takhle: middleware.auth, middleware.region_select, api.orders.parse_json, db.insert_order, queue.enqueue_invoice_job. Názvy držte nudné.
Disciplínu potřebují i metriky. Sledujte p50, p95 a timeout rate zvlášť pro edge a regionální handlery. Sledujte cache hit ratio po routách. Sledujte regionální fan-out, jeden incoming request, který spustí čtyři backend fetches, vám velmi rychle smaže jakýkoliv přínos edge latence. Sledujte DB wait time. Pokud má p95 na edge 18 ms a p95 v regionu 140 ms, z toho 90 ms v db.pool.wait, přesun dalšího kódu na edge vás nespasí. Opravte databázovou cestu.
Anti-pattern je zírat na globální graf syntetické latence a namlouvat si, že edge deployment funguje, protože medián klesl. Mediány lžou. Chování v tailu je to, co hlásí uživatelé, čím trpí support a co manažeři uvidí během dema.
vyberte si předvídatelnost místo chytrosti
Existuje specifický typ architektury, který vypadá skvěle na konferenčních přednáškách a po šesti měsících feature práce je z něj utrpení. Next.js backendy přetížené edge logikou do téhle kategorie padají překvapivě často. To lákadlo je jasné: jedna deploy surface, kód blízko uživatelům, na papíře míň pohyblivých částí. Jenže ten papír lže.
Předvídatelné systémy dávají stavovou logiku blízko ke stavu, routing logiku drží levnou a limity platformy berou jako vstup do návrhu, ne jako drobnost, kterou objevíte až v produkci. Pokud request potřebuje PostgreSQL transakce, nativní moduly, stabilní CPU, širokou podporu balíčků nebo hlubokou observabilitu, pusťte ho v regionálním prostředí, kde se Node.js nebo Python chová jako Node.js nebo Python. Edge použijte na to, aby včas odfiltroval odpad, rychle servíroval cachované response a přidal dost kontextu, aby regionální služba uměla rozhodnout bez opakování stejné práce.
Tohle rozhodnutí navíc pomáhá týmům shipovat rychleji. Inženýři nemusí přemýšlet, jestli je knihovna edge-safe. Code review je jednodušší, protože hranice rout jsou jasné. Incident response je jednodušší, protože v requestu, který selhává, figuruje méně magických execution environments. Kontrola nákladů je jednodušší, protože drahé cesty jsou izolované a měřitelné.
Spousta naší práce ve Steezru nakonec skončí přesně v tomhle tvaru: Next.js řeší customer-facing shell, auth checky a trochu cachingu, Django nebo Node nese těžkou backendovou zátěž a PostgreSQL sedí blízko službám, které do ní zapisují. Není to trendy. Funguje to. Tenhle trade-off beru pokaždé.
