# How to ship a Fastify app on Vercel

**Author:** Ben Sabic

---

[Fastify](https://fastify.dev/) is a fast, low-overhead web framework for building backend servers in Node.js. It pairs a plugin-based architecture with schema-based validation, lifecycle hooks, and built-in logging, and it ships first-class TypeScript support.

On Vercel, you can deploy a Fastify app with zero configuration. Your app runs as a [Vercel Function](https://vercel.com/docs/functions) on [Fluid compute](https://vercel.com/fluid), with preview deployments, instant rollback, and the Vercel Firewall available without extra setup.

This guide walks you through deploying a Fastify app to Vercel from a template, the [Vercel CLI](https://vercel.com/docs/cli), or a Git repository, then configuring features such as streaming, lifecycle hooks, cron jobs, and observability.

## Prerequisites

Before you begin, make sure you have:

- A [Vercel account](https://vercel.com/signup)
  
- Node.js 20+ and a package manager (e.g., npm)
  
- An existing Fastify project, or a new one created from the [Fastify on Vercel template](https://vercel.com/templates/other/fastify-on-vercel)
  
- A Git repository on GitHub, GitLab, or Bitbucket (if you want Git-based deployments)
  
- Vercel CLI installed (`npm i -g vercel`)
  

## How it works

When you deploy a Fastify app, Vercel detects the framework and builds it for the Vercel runtime. Your app is deployed as a single Vercel Function that runs on Fluid compute by default, so it scales with traffic, and you pay only for the compute your function uses, not for idle time.

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

## Deploy your Fastify app

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

### Option 1: Deploy from a template

The fastest way to ship a Fastify app is to start from the [Fastify on Vercel template](https://vercel.com/templates/other/fastify-on-vercel), a minimal Fastify API that deploys with zero configuration. When you deploy it, Vercel clones the template to your Git provider, creates a project, and deploys it.

### Option 2: Start a new project with the Vercel CLI

To scaffold a new Fastify project locally, use the [Vercel CLI init command](https://vercel.com/docs/cli/init). It clones Vercel's [Fastify example](https://github.com/vercel/vercel/tree/main/examples/fastify) into a folder named `fastify`.

1. Create the project:
   
   `vercel init fastify`
   
2. Install dependencies:
   
   `cd fastify npm install`
   
3. Develop locally at `http://localhost:3000` with `vercel dev`, so your app runs the same way it does in production:
   
   `vercel dev`
   
4. Create a [preview deployment](https://vercel.com/docs/deployments/environments#preview-environment-pre-production). The first run links a Vercel project:
   
   `vercel`
   
5. Promote your deployment to production:
   
   `vercel --prod`
   

### Option 3: Deploy an existing Fastify app

If you already have a Fastify 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](https://vercel.com/new). Vercel detects Fastify automatically and deploys it with zero configuration.

From the CLI: From your project's root directory, run `vercel` to create a preview deployment, then `vercel --prod` to go live. To pull project settings and environment variables for local development, run:

`vercel link vercel env pull`

For Vercel to detect your app, name your entry point one of the recognized files, such as `app.ts`, `index.ts`, or `server.ts` at your project root or under `src/`. Create your Fastify instance, register your routes, and start the server with `fastify.listen()`:

`import Fastify from 'fastify'; const fastify = Fastify({ logger: true }); fastify.get('/', async (request, reply) => { return { hello: 'world' }; }); fastify.listen({ port: 3000 });`

## Use Vercel features with Fastify

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`.

### Server routes run as Vercel Functions

Your entire Fastify app is served by a single [Vercel Function](https://vercel.com/docs/functions), which uses Fluid compute by default. Fluid compute 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 your app is deployed as one function, Vercel routes every incoming request to it and lets Fastify's router match the path. Your route handlers, lifecycle hooks, and error handling all run inside the function.

### Stream responses

Vercel Functions support streaming, so you can send data to the client as you produce it instead of waiting for the full response. Fastify streams a response when you return a Node.js Readable stream from a handler. It pipes the stream to the client and ends the response when the stream finishes.

`import Fastify from 'fastify'; import { Readable } from 'node:stream'; const fastify = Fastify(); async function* generateWords() { for (const word of ['Hello', ' ', 'from', ' ', 'Fastify']) { yield word; } } fastify.get('/stream', (request, reply) => { reply.header('Content-Type', 'text/plain; charset=utf-8'); return reply.send(Readable.from(generateWords())); }); fastify.listen({ port: 3000 });` Streaming pairs well with Fluid compute: while your function waits between chunks, the same instance can serve other requests. To stream model output, send a stream from [AI SDK](https://ai-sdk.dev/docs/foundations/streaming) directly. Return `result.textStream` for plain text, or `result.toUIMessageStream()` to stream structured UI messages from `streamText`:

`import { streamText } from 'ai'; import Fastify from 'fastify'; const fastify = Fastify(); fastify.post('/chat', async (request, reply) => { const result = streamText({ model: 'openai/gpt-4o', prompt: 'Invent a new holiday and describe its traditions.', }); reply.header('Content-Type', 'text/plain; charset=utf-8'); return reply.send(result.textStream); }); fastify.listen({ port: 3000 });`

### Combine Fastify lifecycle hooks with Vercel Routing Middleware

Fastify and Vercel each have a layer for running code around requests, and they solve different problems. Fastify's [lifecycle hooks](https://fastify.dev/docs/latest/Reference/Hooks/) run inside your app, after the request reaches your function. Use them for app-level concerns such as logging, authentication, and request processing, and register them with `fastify.addHook`:

`import Fastify from 'fastify'; const fastify = Fastify(); fastify.addHook('onRequest', async (request, reply) => { // Runs before the route handler console.log('Request:', request.url); }); fastify.addHook('onResponse', async (request, reply) => { // Runs after the response is sent console.log('Response sent'); }); fastify.get('/', async () => ({ hello: 'world' })); fastify.listen({ port: 3000 });`

[Vercel Routing Middleware](https://vercel.com/docs/routing-middleware) runs at the edge, before the request reaches your Fastify 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 Fastify's hooks handling it inside your app.

### Run scheduled tasks with cron jobs

Vercel [Cron Jobs](https://vercel.com/docs/cron-jobs) trigger a route on a schedule by sending an HTTP GET request to it. Define a route in your Fastify app for the task, then register the schedule in `vercel.json`.

Define the route:

``import Fastify from 'fastify'; const fastify = Fastify(); fastify.get('/api/cron/cleanup', async (request, reply) => { if (request.headers.authorization !== `Bearer ${process.env.CRON_SECRET}`) { return reply.code(401).send('Unauthorized'); } // Run your scheduled work here return { ok: true }; }); fastify.listen({ port: 3000 });``

**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](https://vercel.com/d?to=%2F%5Bteam%5D%2F%5Bproject%5D%2Fsettings%2Fenvironment-variables). Vercel sends it as a Bearer token in the Authorization header on every cron invocation, and your handler compares it before running the task.

### Monitor performance with Observability

[Vercel Observability](https://vercel.com/products/observability) tracks your deployed functions automatically, with no setup. Open the [Observability page](https://vercel.com/d?to=%2F%5Bteam%5D%2F~%2Fobservability) in your project to see invocation counts, error rates, and duration for your Fastify app, along with the requests your functions make to external APIs. On [Observability Plus](https://vercel.com/docs/observability/observability-plus), you also get longer retention and a latency breakdown by path.

## Best practices

### Name your entry point file correctly

Vercel finds your Fastify app by looking for an entry point at a fixed set of locations: `app`, `index`, or `server` (with a `.js`, `.ts`, `.mjs`, `.cjs`, `.mts`, or `.cts` extension) at your project root or under `src/`. Put your app at one of these paths so Vercel detects and deploys it correctly:

`import Fastify from 'fastify'; const fastify = Fastify({ logger: true }); // Add your routes here fastify.listen({ port: 3000 });`

Create your Fastify instance, register your routes, and call `fastify.listen()` in this file. Vercel uses it as the function entry point for every request.

### Develop with the Vercel CLI

Run `vercel dev` for local development instead of starting the server another way. It serves your app the same way production does, so the behavior you test locally matches what you deploy. This also lets you exercise features such as cron routes before shipping. Vercel CLI 48.6.0 or later is required.

## Resources and next steps

- Read the full [Fastify on Vercel documentation](https://vercel.com/docs/frameworks/backend/fastify)
  
- Deploy the [Fastify on Vercel template](https://vercel.com/templates/other/fastify-on-vercel) in one step
  
- Learn how [Vercel Functions](https://vercel.com/docs/functions) run your server code
  
- Understand pricing and scaling with [Fluid compute](https://vercel.com/docs/fluid-compute)
  
- Run code before requests with [Routing Middleware](https://vercel.com/docs/routing-middleware)
  
- Recover from bad deploys with [Instant Rollback](https://vercel.com/docs/instant-rollback)
  
- Explore the [Fastify documentation](https://fastify.dev/docs/latest/) for framework details

---

[View full KB sitemap](/kb/sitemap.md)
