Nitro logoNitro

Vercel

Deploy Nitro apps to Vercel.

Preset: vercel

Read more in Vercel Framework Support.
Integration with this provider is possible with zero configuration.

Getting started

Deploying to Vercel comes with the following features:

And much more. Learn more in the Vercel documentation.

Deploy with Git

Vercel supports Nitro with zero-configuration. Deploy Nitro to Vercel now.

Observability

Nitro (>=2.12) generates routing hints for functions observability insights, providing a detailed view of performance broken down by route.

To enable this feature, ensure you are using a compatibility date of 2025-07-15 or later.

export default defineNitroConfig({
    compatibilityDate: "2025-07-15", // or "latest"
})

Framework integrations can use the ssrRoutes configuration to declare SSR routes. For more information, see #3475.

Bun runtime

Read more in Vercel.

You can use Bun instead of Node.js by specifying the runtime using the vercel.functions key inside nitro.config:

nitro.config.ts
export default defineNitroConfig({
  vercel: {
    functions: {
      runtime: "bun1.x"
    }
  }
})

Alternatively, Nitro also detects Bun automatically if you specify a bunVersion property in your vercel.json:

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

Queues

Read more in Vercel Queues.

Nitro integrates with Vercel Queues to process messages asynchronously. Define your queue topics in the Nitro config and handle incoming messages with the vercel:queue runtime hook.

nitro.config.ts
export default defineNitroConfig({
  vercel: {
    queues: {
      triggers: [
        // Only `topic` is required
        { topic: "notifications" },
        { topic: "orders", retryAfterSeconds: 60, initialDelaySeconds: 5 },
      ],
    },
  },
});
The @vercel/queue package is required when using queues. Install it in your project with your package manager.

Handling messages

Use the vercel:queue hook in a Nitro plugin to process incoming queue messages:

server/plugins/queues.ts
export default defineNitroPlugin((nitro) => {
  nitro.hooks.hook("vercel:queue", ({ message, metadata, send }) => {
    console.log(`[${metadata.topicName}] Message ${metadata.messageId}:`, message);
  });
});

Running tasks from queue messages

You can use queue messages to trigger Nitro tasks:

server/plugins/queues.ts
import { runTask } from "nitropack/runtime";

export default defineNitroPlugin((nitro) => {
  nitro.hooks.hook("vercel:queue", async ({ message, metadata }) => {
    if (metadata.topicName === "orders") {
      await runTask("orders:fulfill", { payload: message });
    }
  });
});

Sending messages

Use the @vercel/queue package directly to send messages to a topic:

server/routes/api/orders.post.ts
import { send } from "@vercel/queue";

export default defineEventHandler(async (event) => {
  const order = await readBody(event);
  const { messageId } = await send("orders", order);
  return { messageId };
});

Custom build output configuration

You can provide additional build output configuration using vercel.config key inside nitro.config. It will be merged with built-in auto-generated config.

On-Demand incremental static regeneration (ISR)

On-demand revalidation allows you to purge the cache for an ISR route whenever you want, foregoing the time interval required with background revalidation.

To revalidate a page on demand:

  • Create an Environment Variable which will store a revalidation secret
    • You can use the command openssl rand -base64 32 or Generate a Secret to generate a random value.
  • Update your configuration:
    export default defineNitroConfig({
      vercel: {
        config: {
          bypassToken: process.env.VERCEL_BYPASS_TOKEN
        }
      }
    })
    
  • To trigger "On-Demand Incremental Static Regeneration (ISR)" and revalidate a path to a Prerender Function, make a GET or HEAD request to that path with a header of x-prerender-revalidate: bypassToken. When that Prerender Function endpoint is accessed with this header set, the cache will be revalidated. The next request to that function should return a fresh response.

Fine-grained ISR config via route rules

By default, query paramas are ignored by cache.

You can pass an options object to isr route rule to configure caching behavior.

  • expiration: Expiration time (in seconds) before the cached asset will be re-generated by invoking the Serverless Function. Setting the value to false (or isr: true route rule) means it will never expire.
  • group: Group number of the asset. Prerender assets with the same group number will all be re-validated at the same time.
  • allowQuery: List of query string parameter names that will be cached independently.
    • If an empty array, query values are not considered for caching.
    • If undefined each unique query value is cached independently.
    • For wildcard /** route rules, url is always added
  • passQuery: When true, the query string will be present on the request argument passed to the invoked function. The allowQuery filter still applies.
  • exposeErrBody: When true, expose the response body regardless of status code including error status codes. (default false
export default defineNitroConfig({
  routeRules: {
    "/products/**": {
      isr: {
        allowQuery: ["q"],
        passQuery: true,
        exposeErrBody: true
      },
    },
  },
});

Vercel edge functions

Preset: vercel_edge (deprecated)

We recommend migrating to the default Node.js runtime and enabling Fluid compute.