Skip to content

Deployment and Runtimes

orva app code is organized around app.fetch(request), so platform differences are mostly isolated in the adapter layer.

Choosing a platform

Target platformRecommended entryTypical use case
Node.jsserveNodeStandard API services, containers, PM2, systemd
BunserveBunLightweight high-performance experiments or native Bun deployment
DenoserveDenoNative Deno HTTP services
CloudflarecreateCloudflareWorkerEdge APIs and global low-latency distribution
VercelcreateAppRouteHandler createVercelEdgeHandlerApp Router and Edge Route handlers
AWS LambdacreateAWSLambdaHandlerAPI Gateway + Lambda
NetlifycreateNetlifyFunctionHandler createNetlifyEdgeHandlerFunctions and Edge Functions
AzurecreateAzureFunctionHandlerAzure Functions

See Adapters for the complete list.

Node.js deployment

ts
import { createOrva } from 'orvajs';
import { serveNode } from 'orvajs/adapters/node';

const app = createOrva().get('/health', (c) => c.json({ ok: true }));

serveNode(app, { port: Number(process.env.PORT ?? 3000) });

Good fits:

  • Docker / Kubernetes
  • ECS / Fly.io / Railway / Render
  • self-hosted VMs with systemd or PM2

Edge and serverless deployment

Keep app independent. Let the platform entry only wire it up:

ts
import { createOrva } from 'orvajs';
import { createCloudflareWorker } from 'orvajs/adapters/cloudflare';

export const app = createOrva().get('/health', (c) => c.json({ ok: true }));

export default createCloudflareWorker(app);

Recommended layout:

text
src/
  app.ts
platform/
  node.ts
  cloudflare.ts
  lambda.ts

Reusing one business app across platforms

ts
// src/app.ts
export const app = createOrva()
  .get('/health', (c) => c.json({ ok: true }))
  .post('/users', createUserHandler);
ts
// platform/node.ts
import { serveNode } from 'orvajs/adapters/node';
import { app } from '../src/app';

serveNode(app, { port: 3000 });
ts
// platform/vercel.ts
import { createAppRouteHandler } from 'orvajs/adapters/vercel';
import { app } from '../src/app';

export const { GET, POST, PUT, DELETE, PATCH } = createAppRouteHandler(app);

Production recommendations

Node services

  • Use boundary middleware such as secureHeaders(), compress(), and etag() in front of the app.
  • Mount logging, request IDs, and response timing globally.
  • Prefer serving static assets through a CDN or gateway; only use serveStatic() in-app when you need framework-level hosting.

Serverless and edge

  • Avoid reconnect-heavy work or CPU-heavy initialization at module load time.
  • Isolate large dependencies to the routes that actually need them.
  • Prefer granular submodule imports to keep deployment bundles smaller.

Environment variable guidance

ts
const port = Number(process.env.PORT ?? 3000);
const isProd = process.env.NODE_ENV === 'production';
const apiBase = process.env.API_BASE_URL ?? 'http://localhost:3000';

Prefer handling these outside the app itself:

  • environment validation
  • secret injection
  • logging and monitoring SDK initialization

Pre-release checklist

  1. pnpm typecheck
  2. pnpm test
  3. pnpm build
  4. pnpm docs:build
  5. check package.json exports and the publish file list
  6. confirm each platform entry is only a thin adapter and does not mix in business logic

Common deployment patterns

ScenarioRecommendation
Internal enterprise APINode + serveNode() + reverse proxy
Public BFFNode / Bun + cors secureHeaders bodyLimit rateLimit
Global low-latency endpointsCloudflare / Vercel Edge
Pay-per-use functionsAWS Lambda / Netlify / Azure

If you are comparing options, continue with FAQ.

Built with VitePress. Structured for production docs, multilingual delivery and long-term versioning.