Az 1. modulban megértetted, mi a Worker. Most azt nézzük meg, hogyan dolgozol vele nap mint nap: mit tud a runtime, hol vannak a határai, mennyi Node-kódod működik változtatás nélkül, és milyen a lokális fejlesztési élmény.
Egy Express-appban van egy hosszú életű processz, ami app.listen(3000)-rel portot nyit, és middleware-láncokon át kezel mindent. A Workernél nincs „listen": a runtime (a nyílt forráskódú workerd) eseményekkel hívja meg a kódodat. Amilyen típusú eseményre exportálsz handlert, olyanra reagál a Workered:
export default {
// HTTP kérés — az Express route-ok helyett
async fetch(request, env, ctx) { return new Response("hello"); },
// ütemezett futás — a cron/EventBridge helyett (7. modul)
async scheduled(event, env, ctx) { /* napi riport, cleanup… */ },
// üzenetsor-fogyasztás — az SQS consumer helyett (7. modul)
async queue(batch, env, ctx) { /* batch.messages feldolgozása */ },
};
Vagyis ami az AWS-en három külön deploy-egység lenne (web app + cron Lambda + SQS consumer Lambda), az itt lehet egyetlen Worker három handlerrel — közös kóddal, közös bindingokkal.
A harmadik paraméter, a ctx (ExecutionContext) a Worker-életciklus kulcsa. Alapszabály: amint a fetch visszaadja a Response-t, a runtime lezárhatja a munkát. Ha a válasz után még dolgozni akarsz — log kiírása, analitika, cache-frissítés —, azt a ctx.waitUntil()-lal kell „életben tartanod":
async fetch(request, env, ctx) {
const data = await handleRequest(request, env);
// a választ NEM késlelteti, de a runtime megvárja a hátteret:
ctx.waitUntil(logToAnalytics(env, request, data));
return Response.json(data);
}
res.send() után nyugodtan futhat tovább kód a processzben. Workersben egy „elfelejtett" (nem await-elt, nem waitUntil-ozott) promise csendben megszakadhat a válasz után. Ha háttérmunka kell: ctx.waitUntil() — vagy ha komolyabb, Queues (7. modul).Beanstalkon te döntöd el, mikor lépsz Node 20-ról 22-re — platform-frissítéskor minden viselkedésváltozást egyszerre kapsz meg. A Workers ehelyett compatibility date-tel dolgozik: a konfigban rögzített dátum azt mondja meg, hogy a runtime melyik napi viselkedését kéred. A Cloudflare folyamatosan frissíti a platformot, de a változtatásokat dátumhoz (vagy explicit compatibility flaghez) köti — a te Workered viselkedése soha nem változik meg alattad, amíg a dátumot nem emeled. Ez a „soha nem törünk el élő appot" garancia platform-szinten.
nodejs_compat rétegEz a te szempontodból az egyik legfontosabb kérdés, hiszen évek npm-függősége jön veled. A helyzet 2026-ban sokkal jobb, mint a Workers hírneve alapján gondolnád. A nodejs_compat flag bekapcsolásával a Node API-k nagy része natívan, a runtime-ban implementálva elérhető, a maradékot pedig a Wrangler polyfillekkel (unenv) hidalja át bundle-öléskor.
| Node API | Állapot Workersben | Megjegyzés |
|---|---|---|
node:buffer, node:path, node:events, node:stream, node:util, node:zlib | ✔ natív | a leggyakoribb npm-függőségi igények |
node:crypto, node:tls | ✔ natív | teljes crypto API — JWT, aláírás, titkosítás megy |
node:net, node:dns, node:timers | ✔ natív | kimenő TCP-socket is — ezen áll a Postgres-driver (4. modul) |
AsyncLocalStorage (node:async_hooks) | ✔ natív | request-kontextus, logger-korreláció — ahogy megszoktad |
node:fs | ◐ virtuális | kérésenkénti, izolált, nem perzisztens fájlrendszer — configolvasásra jó, tárolásra nem (arra R2) |
process.env, process.nextTick… | ◐ részleges | a process.env-et a bindings/vars táplálják |
net.Server, http.Server — portnyitás | ✘ soha | nincs „listen": a platform hívja a handleredet, nem fordítva |
child_process, natív addonok (.node) | ✘ nem | nincs OS-processz az isolate-ben — ha kell: Containers |
{
"compatibility_date": "2026-08-02",
"compatibility_flags": ["nodejs_compat"] // ennyi — a többit a Wrangler intézi
}
[unenv] ... is not implemented yet! hibát dob futáskor, ezért mindig próbáld ki lokálisan az új függőséget.A legfontosabb fogalompár, amit meg kell szokni: a Workers nem azt méri (és számlázza), meddig él a kérésed, hanem hogy mennyit dolgozik közben a CPU. Amíg a Worker adatbázisra, fetch-re vagy R2-re várakozik, az nem számít CPU-időnek — és nem is kerül pénzbe.
A fontosabb határok (Paid plan, ami éles rendszerhez reális):
| Limit | Free | Paid | Mit jelent neked |
|---|---|---|---|
| CPU-idő / kérés | 10 ms | 30 s alap, konfigurálhatóan 5 percig | API-knak bőven elég; nehéz számításnak (képfeldolgozás, nagy JSON-ok) tervezés kell |
| Memória / isolate | 128 MB | nem tölthetsz be gigabájtos adatot — streamelj (lásd lent) | |
| Worker mérete (gzip) | 3 MB | 10 MB | a bundle számít — a monorepo-szintű függőséghalmot karcsúsítani kell |
| Subrequest / kérés | 50 | 10 000 (10 M-ig emelhető) | minden fetch, KV/D1/R2 hívás egy subrequest |
| Egyidejű kimenő kapcsolat | 6 | a Promise.all(50 fetch) sorban áll — batchelj okosan | |
| Indulási idő | 1 s | a top-level (import-időben futó) kódod legyen könnyű | |
A limiteket lefelé is állíthatod védelemként (elszabadult kód vagy költség ellen), felfelé pedig a konfigban:
wrangler.jsonc{
"limits": {
"cpu_ms": 300000, // 5 perc — pl. nehéz feldolgozáshoz
"subrequests": 50000 // ha sok szolgáltatáshívásod van
}
}
Ha egy Worker túllépi a CPU-limitet, a kliens 1102-es hibát kap (exceededCpu a metrikákban). A megoldási sorrend: profilozd (DevTools CPU-profil), optimalizálj, vagy szervezd ki a nehéz munkát — Queues-ba, Workflows-ba, Durable Objectbe (7. modul), végső esetben Containersbe. A 128 MB memóriára pedig a streaming a válasz: a Response body lehet stream, tehát egy nagy R2-fájlt úgy szolgálsz ki, hogy soha nincs egyben a memóriában.
Beanstalk-világban a „lokális fejlesztés" gyakran azt jelenti: fut a Node lokálisan, de az SQS-t, S3-at mockolod, vagy dev-AWS-fiókra csatlakozol. A Workers-nél a helyzet jobb, mert maga a runtime fut a gépeden: a wrangler dev ugyanazt a workerd motort indítja el lokálisan (ezt a becsomagolást hívják Miniflare-nek), a bindingokkal együtt:
# lokális dev szerver: http://localhost:8787
npx wrangler dev
# a KV, D1, R2, Queues bindingok LOKÁLIS szimulációval mennek,
# perzisztens állapotuk a .wrangler/state mappába kerül
# ha éles erőforrások ellen akarsz fejleszteni:
npx wrangler dev --remote
wrangler dev — az alap: lokális workerd, szimulált bindingok, azonnali reload. A lokális D1 egy igazi SQLite-fájl, a lokális R2 a diszkre ír — offline is fejlesztesz..dev.vars — lokális secretek fájlja (a .env megfelelője), git-ignore-olva; élesben a wrangler secret put az útja (8. modul).wrangler types — legenerálja az Env TypeScript-típusát a konfigod bindingjaiból, tehát az env.MY_BUCKET típusos lesz.| Szokásod eddig | Új megfelelője |
|---|---|
npm run dev (Node lokálisan) | wrangler dev / Vite plugin (workerd lokálisan) |
.env fájl | .dev.vars lokálisan + vars/secrets a konfigban |
eb deploy (percek) | wrangler deploy (másodpercek, globális) |
| Node-verzió upgrade | compatibility date emelése (kontrollált, dátumhoz kötött) |
console.log → CloudWatch | console.log → wrangler tail / Workers Logs (9. modul) |
| háttérmunka a response után | ctx.waitUntil() vagy Queues |
| „bírja-e a gép?" (CPU/RAM-grafikonok) | „belefér-e a CPU-ms-be?" (per-kérés gondolkodás) |
A CPU-idő csak a ténylegesen futó kódot méri; I/O-várakozás alatt az isolate nem foglal CPU-t, így azt a Cloudflare nem is számlázza. Egy tipikus, I/O-ra váró API-nál a fali idő 95%-a „ingyen" van — EC2-n ugyanezt az időt instance-óraként fizetted.
[unenv] ... is not implemented yet! hibát dob futáskor. Mi történt, és mik a lehetőségeid?
A csomag olyan Node API-t hív, amit a runtime natívan nem támogat — a Wrangler polyfillje engedte importálni, de a metódushívás hibát dob. Lehetőségek: alternatív (fetch-alapú vagy edge-kompatibilis) csomag keresése, a funkció kiváltása webes API-val, vagy ha tényleg kell a natív Node-környezet: Containers.
ctx.waitUntil(), és mi történik nélküle a válasz után indított promise-szal?
A válasz visszaadása utáni háttérmunka életben tartására. Nélküle a runtime a response után bármikor leállíthatja az isolate munkáját, így a promise csendben megszakadhat.
A runtime folyamatosan frissül mindenkinél, de a viselkedésváltozások dátumhoz kötöttek: a Worker a konfigban rögzített dátum szerinti viselkedést kapja örökre, amíg te nem emeled. Nincs kényszerített platform-upgrade, és nincs „minden változás egyszerre" ugrás.
Streameléssel: az R2-objektum body-ja stream, amit közvetlenül a Response-ba adsz — a fájl sosincs egyben a memóriában, csak átfolyik a Workeren (vagy még jobb: a 6. modulban látott módon közvetlen/cache-elt kiszolgálással).