Edge
Install NextRush on Cloudflare Workers or Vercel Edge, run a hello-world fetch handler, and see what changes when there's no long-running server.
Runtime · Stateless & distributed
No server, no port, global reach. Edge runtimes have no long-running process — your app is a
fetch function invoked per request, deployed to whichever network location is closest to the
caller. Same createApp/createRouter API as Node, but no serve(), no node:* modules, no
filesystem, and no guaranteed shutdown hook. The tradeoff for that global reach is a real set of
platform constraints.
Where Edge fits
| Runtime | Best for | Tradeoff |
|---|---|---|
| Node | Production APIs, long-running servers, full ecosystem | Heavier footprint than Bun or edge |
| Bun | Local dev speed, native TypeScript, fast cold start | Younger ecosystem, some node:* gaps |
| Deno | Secure by default, permission model | Smaller package ecosystem |
| Edge · this page | Global low latency, Cloudflare/Vercel | No long-running server, node:* limited |
| Serverless | Pay-per-request, auto-scaling | Cold starts, no persistent state |
What changes from Node
| Same | Different |
|---|---|
createApp() | No listen() — edge has no port; you export a fetch handler |
createRouter() | No node:* modules — Fetch API only |
| Route registration | Lazy boot — app boots on first request, not at startup |
| Context API | No shutdown hook — Extension.destroy() not guaranteed |
| Middleware | Platform CLI needed — wrangler or vercel |
"Partial" means the adapter is functionally complete (Beta, Internal tier — see ADR-0005) but not yet verified against the real platform in CI (see the compatibility matrix) — not that it's missing features.
Targeting a different runtime? Node · Bun · Deno · Serverless each implement the same Context and Application contract. Not sure which one fits? See the runtime decision guide.
Before you begin
- ✓ A terminal and a package manager
- ✓ An account with your target platform (Cloudflare or Vercel) if you plan to deploy
- ✓ ~10 minutes
Choose a target platform and its CLI
- Why this matters:
@nextrush/adapter-edgetargets the Fetch API standard, not one platform's SDK — but you still need that platform's CLI to run and deploy.
npm install -g wrangler
wrangler --versionnpm install -g vercel
vercel --versionBehind the scenes: the same @nextrush/adapter-edge package produces both platforms' handler
shape — createCloudflareHandler returns Cloudflare's { fetch } module export, and
createVercelHandler returns the plain function Vercel's Edge runtime expects.
Install NextRush and the edge adapter
- Why this matters: like Bun and Deno, the
nextrushmeta-package does not bundle a runtime adapter — you add@nextrush/adapter-edgealongside it.
$ pnpm add nextrush @nextrush/adapter-edge
Behind the scenes:
createAppandcreateRouterstill come fromnextrush— runtime-independent- Handler factories (
createCloudflareHandler,createVercelHandler,createFetchHandler) come from@nextrush/adapter-edge - Edge has no
listen()at all — there is no port to listen on
Run a hello-world fetch handler
Create the handler for your platform:
import { createApp, createRouter } from 'nextrush';
import { createCloudflareHandler } from '@nextrush/adapter-edge';
const app = createApp();
const router = createRouter();
router.get('/', (ctx) => {
ctx.json({ runtime: ctx.runtime, status: 'ok' });
});
app.route('/', router);
export default createCloudflareHandler(app);name = "my-nextrush-worker"
main = "src/index.ts"
compatibility_date = "2025-01-01"Run locally, then deploy:
wrangler dev
wrangler deployimport { createApp, createRouter } from 'nextrush';
import { createVercelHandler } from '@nextrush/adapter-edge';
const app = createApp();
const router = createRouter();
router.get('/', (ctx) => {
ctx.json({ runtime: ctx.runtime, status: 'ok' });
});
app.route('/', router);
export const config = { runtime: 'edge' };
export default createVercelHandler(app);Run locally, then deploy:
vercel dev
vercelExpected result — curl https://your-worker.workers.dev/ returns {"runtime": "cloudflare-workers", "status": "ok"}
Behind the scenes:
createCloudflareHandler(app)returns{ fetch },createVercelHandler(app)returns the fetch function directly- Both wrap the same internal request runner — lazily boots on first request, then reuses the handler
ctx.runtimereports'cloudflare-workers'or'vercel-edge'depending on where the code runs
What's structurally different about edge
Your handler is deployed. Before moving on, understand what's genuinely different — and what isn't.
Same: the Context API, createApp, createRouter, route registration, and middleware all
behave identically to Node. Nothing in your route handler is edge-specific.
Different: edge runtimes give you a fetch function invoked per request, not a process you
start — so @nextrush/adapter-edge has no serve()/listen() at all. The application boots
lazily on the first request instead of upfront. One consequence: Extension.destroy() teardown
(timers, connections) is not guaranteed to run — edge platforms give you no shutdown hook.
No teardown on edge
Extension.destroy() is not guaranteed to run — there is no shutdown hook on Cloudflare Workers
or Vercel Edge. Don't rely on extension teardown for correctness on edge; design for it to be skipped.
Edge runtime working — deployed at the network edge, no server to manage.
Edge baseline complete
Confirm the handler answers:
curl -i https://your-worker.workers.dev/
# → HTTP/1.1 200 OK
# → {"runtime":"cloudflare-workers","status":"ok"}Your project now looks like (Cloudflare Workers shown):
my-worker/
wrangler.toml
src/
index.tsBaseline complete — deployed at the edge, answering from the network location closest to the caller.
What you learned
- ✓
nextrushgives you the runtime-independent half —createApp,createRouter, and route registration are identical on edge and Node - ✓ The handler factories come from
@nextrush/adapter-edge, not the meta-package — and there is nolisten()because there is no port - ✓ The app boots lazily on the first request, and teardown never runs — a direct consequence of edge having no startup or shutdown hook
The same app, every runtime
The code you just wrote runs on every runtime NextRush supports. Only the adapter import changes:
- createApp()
- Router
- Handler
- Edge adapter
- Running
// Node: import { listen } from '@nextrush/adapter-node';
// Bun: import { listen } from '@nextrush/adapter-bun';
// Deno: import { listen } from '@nextrush/adapter-deno';
// Edge: import { serve } from '@nextrush/adapter-edge'; // ← you are here
// Serverless import { handler } from '@nextrush/adapter-serverless';Next steps
🚀 Build a Task API — recommended · ~20 min
Go past hello-world on the runtime you set up: routing, a JSON body, and a real 404. Start the tutorial →
Deploy to production
Cloudflare Workers, Vercel Edge, and Netlify Edge deployment paths for a NextRush app.
Edge adapter reference
The full @nextrush/adapter-edge surface — createFetchHandler(), createCloudflareHandler(), createVercelHandler(), and edge-specific utilities.
Continue learning
Deno
Install NextRush on Deno, run a hello-world server on Deno.serve(), and see what Deno's permission model means for your NextRush app.
Serverless
Install NextRush on AWS Lambda, Google Cloud Functions, or Azure Functions, and see what warm-instance reuse and per-invocation timeouts mean for your app.