---
title: "Vercel"
description: "Use Vercel for MainSDK cache, background jobs, runtime settings and feature flags - Runtime Cache, Queues, Global Config, Flags, main.yaml and swapping."
section: "integrations"
canonical: "https://mainsdk.dev/docs/integrations/vercel"
updated: "2026-10-28"
---

# Vercel

> Use Vercel for MainSDK cache, background jobs, runtime settings and feature flags - Runtime Cache, Queues, Global Config, Flags, main.yaml and swapping.

Canonical: https://mainsdk.dev/docs/integrations/vercel · Updated: 2026-10-28

If your app runs on Vercel, four of its platform services can sit behind MainSDK interfaces: Vercel Runtime Cache behind [`kv`](https://mainsdk.dev/docs/interfaces/kv), Vercel Queues behind [`jobs`](https://mainsdk.dev/docs/interfaces/jobs), Vercel Global Config (formerly Edge Config) behind [`config`](https://mainsdk.dev/docs/interfaces/config), and Vercel Flags behind [`flags`](https://mainsdk.dev/docs/interfaces/flags). Your code calls the same interfaces it would on any host, and the services live in the Vercel project you already deploy. Pick these drivers when you deploy on Vercel and want fewer outside accounts; pick each one separately, since every interface has its own driver line.

For deploying a MainSDK app on Vercel (secrets as references, the check on every preview, the firewall export), see [Deploy on Vercel](https://mainsdk.dev/docs/guides/deploy-vercel).

> **Note:** `kv` and `flags` have no spec yet. Their calls and options on this page are provisional, taken from the catalog and the product requirements, and may change when the spec lands. `jobs` comes with the webhooks-jobs spec and `config` with the config-secrets spec.

## Interfaces it serves

### Key-value store and cache (`kv`)

- Status: Building for 0.3 · ships as a beta API
- Driver: `vercel-runtime-cache` (Vercel Runtime Cache). planned
- Docs: https://mainsdk.dev/docs/interfaces/kv.md

```yaml
kv:
  driver: vercel-runtime-cache
```

Swap to another provider: `local`, `redis`, `upstash`, `cloudflare-kv`.

### Durable workflows (`workflows`)

- Status: Preview · ships as a beta API
- Driver: `vercel-workflow` (Vercel Workflow). later
- Docs: https://mainsdk.dev/docs/interfaces/workflows.md

```yaml
workflows:
  driver: vercel-workflow
```

Swap to another provider: `db`, `local`, `inngest`, `temporal`.

### Events and background jobs (`jobs`)

- Status: Building for 0.3 · ships as a stable API
- Driver: `vercel-queues` (Vercel Queues). not built yet; the webhooks-jobs spec names it
- Docs: https://mainsdk.dev/docs/interfaces/jobs.md

```yaml
jobs:
  driver: vercel-queues
```

Swap to another provider: `db`, `local`, `inngest`, `trigger-dev`, `sqs`.

### Code sandboxes (`sandbox`)

- Status: Building for 0.4 · ships as a beta API
- Driver: `vercel-sandbox` (Vercel Sandbox, default)
- Docs: https://mainsdk.dev/docs/interfaces/sandbox.md

```yaml
sandbox:
  driver: vercel-sandbox
```

Swap to another provider: `e2b`, `local`.

### Deploy config and serverless schedules (`deploy`)

- Status: Building for 0.4 · ships as a beta API
- Driver: `vercel` (Vercel, default)
- Docs: https://mainsdk.dev/docs/interfaces/deploy.md

```yaml
deploy:
  driver: vercel
```

Swap to another provider: `cloudflare`, `fly`, `docker`.

### Runtime settings (`config`)

- Status: Building for 0.2 · ships as a stable API
- Driver: `vercel-global-config` (Vercel Global Config). planned
- Docs: https://mainsdk.dev/docs/interfaces/config.md

```yaml
config:
  driver: vercel-global-config
```

Swap to another provider: `files`, `local`, `redis`, `postgres`, `aws-appconfig`, `cloudflare-kv`.

### Feature flags (`flags`)

- Status: Preview · ships as a beta API
- Driver: `vercel-flags` (Vercel Flags). planned; through the openfeature driver
- Docs: https://mainsdk.dev/docs/interfaces/flags.md

```yaml
flags:
  driver: vercel-flags
```

Swap to another provider: `config`, `openfeature`, `posthog`.

## Before you start

You need a Vercel account and a project linked to your repository.

1. **Runtime Cache** is part of the Vercel functions runtime for your project; there is no store to create.
2. **Queues:** enable Vercel Queues for the project and decide which topics your jobs use.
3. **Global Config:** create a Global Config store, connect it to the project, and add your settings as items.
4. **Flags:** create your flags and targeting rules in Vercel Flags for the project.
5. **Environment variables:** connecting a store to the project can add its connection variable for you. Add any other keys MainSDK reads with `vercel env add`, per environment, and refer to them in `main.yaml` as `secret:NAME` through `secrets: { driver: env }`.

How each Vercel driver authenticates to its service is not defined yet [TBD].

## Configure

Runtime Cache for `kv`:

```yaml title="main.yaml"
kv:
  driver: vercel-runtime-cache
```

Queues for `jobs`:

```yaml title="main.yaml"
jobs:
  driver: vercel-queues
  dead-letter: true
idempotency: { store: db, ttl: 24h }
```

Global Config for `config`:

```yaml title="main.yaml"
config:
  driver: vercel-global-config
  schema: ./config.schema.json
```

Flags for `flags`:

```yaml title="main.yaml"
flags:
  driver: vercel-flags
```

Connection keys for each service (store id, project, SDK key) are not decided yet; when they are, they go in as `secret:` references [TBD].

## Use it

Cache a slow lookup in Runtime Cache:

```ts title="lib/prices.ts"
import { cache } from "mainsdk";

export async function pricesFor(market: string) {
  return cache.wrap(`prices:${market}`, () => loadPrices(market), { ttl: "5m", tags: ["prices"] });
}
```

Run a job on Vercel Queues:

```ts title="app/api/reports/route.ts"
import { auth, jobs } from "mainsdk";

export async function POST(req: Request) {
  const session = await auth.require(req);
  const { month } = await req.json();
  await jobs.run(
    "reports.export",
    { userId: session.user.id, month },
    { idempotencyKey: `export:${session.user.id}:${month}`, retries: 3, backoff: "exponential" },
  );
  return new Response(null, { status: 202 });
}
```

Read a setting from Global Config:

```ts title="app/api/cart/route.ts"
import { auth, config } from "mainsdk";

export async function POST(req: Request) {
  await auth.require(req);
  const { items } = await req.json();
  const max = config.get("cart.maxItems");   // typed from config.schema.json
  return items.length > max
    ? Response.json({ error: `Keep the cart to ${max} items` }, { status: 422 })
    : Response.json({ ok: true });
}
```

Check a flag in Vercel Flags:

```ts title="app/api/checkout/route.ts"
import { auth, flags } from "mainsdk";

export async function GET(req: Request) {
  const session = await auth.require(req);
  const useNew = await flags.enabled("new-checkout", { for: session.user });
  return Response.json({ checkout: useNew ? "new" : "classic" });
}
```

## Local development and testing

- **No Vercel services:** keep local drivers in `main.env.dev.yaml`: `config: { driver: files }` and the in-process local queue for `jobs` (its driver id is [TBD]). `mainsdk check --env prod` refuses local drivers in production.
- **Tests:** `createTestApp()` from `@mainsdk/testing` runs `kv`, `jobs`, `config` and `flags` on in-memory fakes, so tests reach no Vercel service. `chaos.on("config", { outage: true })` proves settings keep their last good value; `chaos.on("jobs", { outage: true })` and `chaos.on("kv", { outage: true })` drill the other services.
- **Preview deployments:** each Vercel environment has its own variables, so previews can use their own Global Config store and flag values.

## What MainSDK adds on top

- `kv`: keys scoped per tenant and a TTL on every entry.
- `jobs`: a CloudEvents envelope, retries with backoff, a dead-letter queue, and MainSDK's own idempotency record, so a duplicate key never runs the side effect twice.
- `config`: settings typed against a schema; a bad value is rejected with `MAIN-CONFIG-0020` and the last good one kept, and every change is audited.
- `flags`: flags and targeting stay in Vercel Flags; your code asks one question.

See [Key-value store and cache](https://mainsdk.dev/docs/interfaces/kv), [Events and background jobs](https://mainsdk.dev/docs/interfaces/jobs), [Runtime settings](https://mainsdk.dev/docs/interfaces/config) and [Feature flags](https://mainsdk.dev/docs/interfaces/flags).

## Limits and notes

- Runtime Cache is ephemeral and kept per region: an entry written in one region is not read in another, and entries can be dropped before their TTL. Use it as a cache, never as the only copy.
- `vercel-queues` comes with the webhooks-jobs spec and `vercel-global-config` with the config-secrets spec (both phase 1). `vercel-runtime-cache` and `vercel-flags` are planned phase 1 drivers whose interfaces have no spec yet.
- Delivery on Queues is at least once; MainSDK makes the effects idempotent. Exactly-once delivery is not promised.
- Pick your Vercel function regions to match your data. MainSDK regions are US, EU and India; see [Data and regions](https://mainsdk.dev/docs/concepts/data-and-regions).
- On Vercel, the platform's OIDC token can stand in for the MainSDK Cloud ingest key when you send telemetry (phase 2); see [Deploy on Vercel](https://mainsdk.dev/docs/guides/deploy-vercel).
- `config.raw()` returns the provider's client for features `config` does not wrap; every use is logged and listed by `mainsdk check`.

## Swap to or from it

Each interface swaps on its own line:

```yaml title="main.yaml"
jobs:
  driver: inngest   # was vercel-queues
```

> **Warning:** Queued and scheduled jobs live in Vercel Queues. What happens to them when you change the `jobs` driver is [TBD], so drain the queue before you switch. The idempotency record is MainSDK's own, so a duplicate key stays a duplicate across the swap. For `config` and `flags`, copy your settings and recreate your flags in the new tool first; cached `kv` entries simply refill.

## FAQ

**Do I have to use these drivers to deploy on Vercel?** No. Any driver works on Vercel; these four just keep the services inside your Vercel project.

**Global Config or Vercel Flags?** Use Global Config through `config` for typed values that apply to the whole app, and Vercel Flags through `flags` to turn features on per user or market.

**Does Runtime Cache replace a database?** No. It is an ephemeral cache. Keep records in [`db`](https://mainsdk.dev/docs/interfaces/db), for example on [Neon](https://mainsdk.dev/docs/integrations/neon).

## Next

- [Deploy on Vercel](https://mainsdk.dev/docs/guides/deploy-vercel)
- [Key-value store and cache](https://mainsdk.dev/docs/interfaces/kv), [Events and background jobs](https://mainsdk.dev/docs/interfaces/jobs), [Runtime settings](https://mainsdk.dev/docs/interfaces/config) and [Feature flags](https://mainsdk.dev/docs/interfaces/flags)
- [Neon](https://mainsdk.dev/docs/integrations/neon), [Upstash](https://mainsdk.dev/docs/integrations/upstash), [Inngest](https://mainsdk.dev/docs/integrations/inngest) and [OpenFeature](https://mainsdk.dev/docs/integrations/openfeature)
- [Swap a driver](https://mainsdk.dev/docs/guides/swap-a-driver)
