Skip to content
Docs

How to ship an Elysia app on Vercel

Deploy a Elysia app to Vercel with zero configuration. Learn how to ship from a template, the Vercel CLI, or Git, and configure response streaming, middleware, cron jobs, the Bun runtime, and Observability.

Ben SabicContent Engineer

Elysia is an ergonomic web framework for building backend servers with TypeScript. Designed with simplicity and type safety in mind, it offers a familiar chained API, end-to-end type inference, and built-in support for validation, lifecycle hooks, and response streaming. Elysia is optimized for Bun, and it also runs on Node.js.

On Vercel, you can deploy an Elysia app with zero configuration: your routes become Vercel Functions running on Fluid compute, and you get response streaming, preview deployments, and observability without extra setup.

This guide walks you through deploying an Elysia app to Vercel from a template, the Vercel CLI, or a Git repository, then configuring features such as streaming, lifecycle hooks, cron jobs, the Bun runtime, and observability.

Copy link to headingPrerequisites

Before you begin, make sure you have:

  • A Vercel account
  • Node.js 20+ and a package manager (e.g., npm)
  • An existing Elysia project, or a new one created from the Elysia on Vercel template
  • A Git repository on GitHub, GitLab, or Bitbucket (if you want Git-based deployments)
  • Vercel CLI installed (npm i -g vercel)

Copy link to headingHow it works

When you deploy an Elysia app, Vercel detects the framework and builds it for the Vercel runtime. Your exported Elysia app handles requests through Vercel Functions, which run on Fluid compute by default. Your app scales with traffic, and you pay only for the compute your functions use, not for idle time.

Because Vercel ships zero-configuration detection for Elysia, you don't set a build command or output directory. Vercel reads your project, finds the file that exports your Elysia app, and applies the correct build settings.

Copy link to headingDeploy your Elysia app

You can ship an Elysia app to Vercel in three ways. Choose the one that fits where your code lives today.

Copy link to headingOption 1: Deploy from a template

The fastest way to ship an Elysia app is to start from the Elysia on Vercel template, a minimal Elysia API that deploys with zero configuration. When you deploy it, Vercel clones the template to your Git provider, creates a project, and deploys it.

Copy link to headingOption 2: Start a new project with the Vercel CLI

To scaffold a new Elysia project locally, use the Vercel CLI init command. It clones Vercel's Elysia example into a folder named elysia.

  1. Create the project:
    Terminal
    vercel init elysia
  2. Install dependencies:
    Terminal
    cd elysia
    npm install
  3. Develop locally at http://localhost:3000. Use the Vercel CLI, so your app runs with the same default export it uses in production:
    Terminal
    vercel dev
  4. Deploy your app. The first run links the project, and because it's the project's first deployment, Vercel creates a production deployment:
    Terminal
    vercel
  5. After that, vercel creates preview deployments. Deploy later changes to production with:
    Terminal
    vercel --prod

Copy link to headingOption 3: Deploy an existing Elysia app

If you already have an Elysia app, deploy it from Git or from the command line.

From Git: Push your project to GitHub, GitLab, or Bitbucket, then import it at vercel.com/new. Vercel detects Elysia automatically and deploys it with zero configuration.

From the CLI: From your project's root directory, run vercel to deploy. The first deployment of a new project is a production deployment. After that, vercel creates preview deployments and vercel --prod deploys to production. To pull project settings and environment variables for local development, run:

Terminal
vercel link
vercel env pull

For Vercel to detect your app, export your Elysia instance as the default export from one of the recognized entry files, such as app.ts, index.ts, or server.ts at your project root or under src/:

src/index.ts
// For Node.js, ensure "type": "module" in package.json
// (Not required for Bun)
import { Elysia } from 'elysia';
const app = new Elysia().get('/', () => ({
message: 'Hello from Elysia on Vercel!',
}));
export default app;

Running your application with app.listen() is currently not supported on Vercel. Use the default export instead, and if you're running on Node.js, set "type": "module" in your package.json:

package.json
{
"name": "elysia-app",
"type": "module"
}

Copy link to headingUse Vercel features with Elysia

After your app is deployed, you can layer Vercel features onto it. Some work automatically, and others take a few lines of configuration in vercel.json.

Copy link to headingServer routes run as Vercel Functions

Each route in your Elysia app is served by Vercel Functions. These functions use Fluid compute by default, which runs multiple requests concurrently within a single instance to reduce cold starts and the cost of I/O-bound work such as API calls and database queries. You don't configure anything to get this behavior.

Because Elysia exports a single app, Vercel sends every incoming request to that app and lets Elysia's router match the path. Your route handlers, lifecycle hooks, and error handling all run inside Vercel Functions.

Copy link to headingStream responses

Vercel Functions support streaming, so you can send data to the client as you produce it instead of waiting for the full response. Elysia streams responses out of the box when you write your handler as a generator function with the yield keyword, and the sse utility formats yielded values as server-sent events:

src/index.ts
import { Elysia, sse } from 'elysia';
const app = new Elysia()
.get('/stream', function* () {
for (const chunk of ['Hello', ' ', 'from', ' ', 'Elysia']) {
yield chunk;
}
})
.get('/events', function* () {
yield sse({ event: 'message', data: { status: 'started' } });
yield sse({ event: 'message', data: { status: 'done' } });
});
export default app;

If a client disconnects before the response completes, Elysia automatically stops the generator. Streaming pairs well with Fluid compute: while your function waits between chunks, the same instance can serve other requests. Elysia also accepts a ReadableStream as a return value, which makes it straightforward to stream model output from AI SDK.

Copy link to headingCombine Elysia lifecycle hooks with Vercel Routing Middleware

Elysia and Vercel each have a layer for running code around requests, and they solve different problems. Elysia's plugins and lifecycle hooks run inside your app's router, after the request reaches your function. Use them for app-level concerns such as logging, authentication, and request processing:

src/index.ts
import { Elysia } from 'elysia';
const app = new Elysia()
.onBeforeHandle(({ request }) => {
// Runs before the route handler
console.log('Request:', request.url);
})
.onAfterHandle(({ response }) => {
// Runs after the route handler
console.log('Response sent');
})
.get('/', () => 'Hello Elysia!');
export default app;

Vercel Routing Middleware runs at the edge, before the request reaches your Elysia app. Use it for rewrites, redirects, and header changes that should happen before any function runs. The two layers work together, with Routing Middleware shaping the request at the edge and Elysia's lifecycle hooks handling it inside your app.

Copy link to headingRun scheduled tasks with cron jobs

Vercel Cron Jobs trigger a route on a schedule by sending an HTTP GET request to it. Define a route in your Elysia app for the task, then register the schedule in vercel.json.

Define the route:

src/index.ts
import { Elysia } from 'elysia';
const app = new Elysia().get('/api/cron/cleanup', ({ request, status }) => {
if (
request.headers.get('authorization') !== `Bearer ${process.env.CRON_SECRET}`
) {
return status(401, 'Unauthorized');
}
// Run your scheduled work here
return { ok: true };
});
export default app;

Register the schedule:

{
"$schema": "https://openapi.vercel.sh/vercel.json",
"crons": [{ "path": "/api/cron/cleanup", "schedule": "0 0 * * *" }]
}

Vercel runs cron jobs only on production deployments. To stop anyone else from calling the route, set a CRON_SECRET environment variable in your project settings. Vercel sends it as a Bearer token in the Authorization header on every cron invocation, and your handler compares it before running the task.

Copy link to headingUse the Bun runtime

Elysia runs your functions on Node.js by default. Since Elysia is optimized for Bun, you may want to run them on Bun instead. Set bunVersion in vercel.json:

vercel.json
{
"$schema": "https://openapi.vercel.sh/vercel.json",
"bunVersion": "1.x"
}

Vercel detects the setting, runs your app on Bun in both vercel dev and production, and keeps it on Fluid compute. The Bun runtime is in public beta and supports most Node.js APIs. Set the major version only, and Vercel manages the minor and patch versions. On Bun, you also don't need "type": "module" in your package.json.

Copy link to headingMonitor performance with Observability

Vercel Observability tracks your deployed functions automatically, with no setup. Open the Observability page in your project to see invocation counts, error rates, and duration for your Elysia app, along with the requests your functions make to external APIs. On Observability Plus, you also get longer retention and a latency breakdown by path.

Copy link to headingBest practices

Copy link to headingExport your app from a recognized entry point

Vercel finds your Elysia app by looking for a default export at a fixed set of locations: app, index, or server (with a .js, .ts, or related extension) at your project root or under src/. Put your app at one of these paths so Vercel detects and deploys it correctly:

src/index.ts
import { Elysia } from 'elysia';
const app = new Elysia();
// Add your routes here
export default app;

Remember that app.listen() is not supported on Vercel. Export the app instead, and let Vercel Functions handle the server lifecycle.

Copy link to headingDevelop with the Vercel CLI

Run vercel dev for local development instead of a standalone server. It serves your app the same way production does, using your default export, so the behavior you test locally matches what you deploy. This also lets you exercise features such as cron routes and the Bun runtime before shipping.

Copy link to headingResources and next steps

Related documentation

More Fluid compute guides