Getting StartedChoose Your Runtime

Which Runtime Should I Use?

A decision guide for choosing between Node.js, Bun, Deno, edge, and serverless — the fast answer and the criteria behind each choice.

Decision guide

Five runtimes run the same NextRush application code unmodified. The choice isn't "which one works" — it's "which deployment model fits what you're building." Here's the fast answer, then the reasoning behind it.

5 runtimesSame application codeOne import changes

Already have an app in Next.js (or another framework)?

This page is about choosing a JS runtime for a standalone NextRush app. If you already have — or are creating — a Next.js project and want to mount a NextRush API inside it, that's a different question with its own page: see Next.js integration. Next.js isn't a runtime choice; it runs on whichever runtime it's deployed to.

The fast answer

SituationRecommendation
⭐ New to NextRush, or unsureNode.js
🐳 Deploying with Docker, PM2, or a VPSNode.js
⚡ Fastest local dev loopBun
🔒 Deny-by-default, security-firstDeno
🌍 Cloudflare Workers or Vercel EdgeEdge
☁ AWS Lambda, GCF, or Azure FunctionsServerless

Which package do I actually install? (Cloudflare vs. Lambda/GCF/Azure)

"Edge" and "serverless" both describe event-driven, no-server-to-manage deployment — but they're two different NextRush packages, split by which handler contract the platform speaks, not by vaguely feeling "serverless." This table is the answer, since the split isn't obvious from either package's name alone:

You're deploying to...InstallHandler
Cloudflare Workers@nextrush/adapter-edgecreateCloudflareHandler(app)
Vercel Edge Functions@nextrush/adapter-edgecreateVercelHandler(app)
Netlify Edge Functions@nextrush/adapter-edgecreateNetlifyHandler(app)
AWS Lambda (Function URL / API Gateway)@nextrush/adapter-serverlesscreateLambdaHandler(app)
Google Cloud Functions@nextrush/adapter-serverlesscreateGoogleHandler(app) (alias: createGcfHandler)
Azure Functions@nextrush/adapter-serverlesscreateAzureHandler(app)

The rule of thumb: Cloudflare/Vercel/Netlify speak the Fetch API directly (fetch(request)) — that's @nextrush/adapter-edge. AWS/GCP/Azure hand you a platform-specific event or SDK object — that's @nextrush/adapter-serverless, which is itself built on @nextrush/adapter-edge's engine underneath (one execution model, six front doors). See each package's own README for the full handler reference: adapter-edge, adapter-serverless.

Still unsure? Start with Node.js

Every tutorial, every guide, and every middleware package on this site targets Node first — it's the runtime with zero surprises to design around. Moving to Bun, Deno, edge, or serverless later changes one import, not your route handlers.

Changing your mind later is cheap

Switching runtimes changes the adapter import — @nextrush/adapter-bun, @nextrush/adapter-deno, @nextrush/adapter-edge, or @nextrush/adapter-serverless in place of the Node adapter nextrush bundles by default. Your route handlers, middleware, and the Context API (ctx.json, ctx.params, ctx.query, …) stay exactly the same — see each runtime's own guide for the one import that moves.

By project type

You're building...Reach for
A REST API or backend serviceNode.js
An internal dashboard or admin toolNode.js
A Cloudflare WorkerEdge
A function behind AWS Lambda / API GatewayServerless
A CLI tool or script that also serves HTTPBun
Something handling untrusted or third-party codeDeno

Each runtime, compressed

A tempting reason that's usually wrong

Picking Bun or Deno "because it's faster/newer" with no concrete requirement behind it trades Node's ecosystem and track record for a benefit you may never measure. Picking edge or serverless for a stateful app that assumes a long-running process is the more expensive version of the same mistake.

Comparison reference

Once you've picked a direction above, this is what actually differs underneath. Every row is identical regardless of which runtime you choose except the ones listed:

Node.jsBunDenoEdgeServerless
Process modelLong-runningLong-runningLong-runningPer-request fetchPer-invocation
node:* module accessFullFull (Bun's compat layer)Partial (npm specifiers)NoneNone
FilesystemYesYesYes, with --allow-readNoNo
Default security modelOpenOpenDeny-by-defaultSandboxed by platformSandboxed by platform
Cold startNone (process stays up)None (process stays up)None (process stays up)Lazy boot, first requestCold start per fresh instance
Extension teardown (app.close())Runs normallyRuns normallyRuns normallyNot guaranteedNot guaranteed
Adapter packageBundled in nextrush@nextrush/adapter-bun@nextrush/adapter-deno@nextrush/adapter-edge@nextrush/adapter-serverless
Verified in CI🟢 Real runtime🟢 Real runtime🟢 Real runtime🟢 Cloudflare · 🟡 Vercel🟡 Simulated

"🟢 Real runtime" vs. "🟡 Simulated" reflects how each adapter's conformance suite is verified — see the compatibility matrix for the full breakdown. createApp, createRouter, the Context API, and route handlers behave identically across every row above — nothing in this table changes how you write a handler.

No fabricated performance scores

You won't find star ratings for "startup speed" or "throughput" on this page. The framework's own benchmark numbers are being re-measured on a controlled environment and aren't currently republished — a 1–5 star score with no measurement behind it would be a guess dressed up as data. Run apps/benchmark yourself for numbers specific to your hardware and workload.

Common mistakes

  • Edge isn't for stateful apps — no instance guarantee between requests; shared state needs an external store, on every runtime.
  • Serverless needs module-scope initialization — build the app outside the handler function or warm-instance reuse never kicks in (serverless guide, Step 3).
  • Deno permissions are enforced by Deno, not NextRush--allow-net and friends gate the process itself, before any adapter code runs.

Continue learning

Was this helpful?

On this page