Vercel Functions integration
Vercel offers two function runtimes: the Node.js Serverless Runtime and the lightweight Edge Runtime. This guide covers both. Use @avsbhq/node for Node.js functions where you need full Node APIs, and @avsbhq/edge for Edge Functions where you want the lowest latency possible with a KV-cached datafile.
Node.js runtime
Install
1npm install @avsbhq/node @avsbhq/utilsObtain your SDK key
Go to Settings → Environments in your A vs B project and copy the Server SDK key. Add it to Vercel as an environment variable named AVSB_SDK_KEY. Mark it as secret so it is not included in client bundles.
Bootstrap the server SDK
Declare the AvsbServer instance outside the handler so it is reused across warm invocations.
1import { AvsbServer } from '@avsbhq/node'2import type { VercelRequest, VercelResponse } from '@vercel/node'3
4const server = new AvsbServer({ sdkKey: process.env.AVSB_SDK_KEY! })5
6export default async function handler(req: VercelRequest, res: VercelResponse) {7 await server.onReady()8
9 const userId = (req.headers['x-user-id'] as string) ?? 'anon'10 const avsb = server.forUser({ kind: 'user', key: userId })11
12 const flag = avsb.getFlag('checkout-v2', false)13 res.json({ showNewCheckout: flag.value })14}Read a flag
1const flag = avsb.getFlag('checkout-v2', false)2// flag.value — the typed boolean result3// flag.source — 'rule' | 'default' | 'not_found' | ...4// flag.variationKey — which variation was servedTrack an event
1avsb.track('checkout_started', {2 value: 149.99,3 properties: { currency: 'usd' },4})Identify a user
Pass full user attributes when building the scoped client. You can include any targeting attributes your flag rules depend on.
1const avsb = server.forUser({2 kind: 'user',3 key: userId,4 plan: session.plan,5 country: geoCountry,6})Edge runtime
Vercel Edge Functions run in the V8 isolate environment — no Node.js built-ins, no persistent background timers. The @avsbhq/edge package is designed for exactly this environment. It caches the datafile in Vercel Edge Config so evaluation is local and latency-free.
Install
1npm install @avsbhq/edge @vercel/edge-configConfigure Edge Config
Create an Edge Config store in your Vercel dashboard and note its connection string. Add the environment variable EDGE_CONFIG to your project. You will write the datafile to this store from a webhook or a scheduled cron so the edge runtime can read it without an outbound fetch on each request.
Bootstrap the edge client
1import { AvsbEdgeClient } from '@avsbhq/edge'2import { createClient } from '@vercel/edge-config'3
4export const config = { runtime: 'edge' }5
6// One client per isolate — shared across requests in the same isolate lifecycle.7const edgeConfigStore = createClient(process.env.EDGE_CONFIG!)8
9const avsb = new AvsbEdgeClient({10 sdkKey: process.env.AVSB_SDK_KEY!,11 datafileCache: {12 async get(key: string) {13 const raw = await edgeConfigStore.get<string>(key)14 return raw ?? null15 },16 // Writes are handled by your datafile-refresh webhook — see note below.17 async set(_key: string, _value: string) {},18 },19})20
21export default async function handler(req: Request): Promise<Response> {22 await avsb.onReady()23
24 const userId = req.headers.get('x-user-id') ?? 'anon'25 const scoped = avsb.forUser({ kind: 'user', key: userId })26
27 const flag = scoped.getFlag('new-banner', false)28 return Response.json({ value: flag.value })29}Read a flag
1const flag = scoped.getFlag('new-banner', false)2// flag.value — boolean result3// flag.source — 'rule' | 'default' | 'not_found'Track an event and flush
Edge Functions have a fixed execution window. Use waitUntil from @vercel/functions (if available) to flush events after the response is sent, or call avsb.flush() before returning the response.
1import { waitUntil } from '@vercel/functions'2
3scoped.track('banner_clicked', { value: 1 })4
5// Flush after response — does not delay the response6waitUntil(avsb.flush())7
8return Response.json({ ok: true })SSR hydration in Next.js on Vercel
If you are running a Next.js application on Vercel, use the Next.js App Router integration instead of this page. It handles server-side evaluation and client hydration through the dedicated @avsbhq/next package.
Testing
1import { TestData, createMockClient } from '@avsbhq/test'2import { describe, it, expect } from 'vitest'3
4const td = TestData.flag('checkout-v2')5 .booleanFlag()6 .variationForUser('u_power', true)7 .fallthroughVariation(false)8
9const mock = createMockClient({ flags: [td.build()] })10
11describe('flag evaluation', () => {12 it('returns true for power user', () => {13 const flag = mock.forUser({ kind: 'user', key: 'u_power' }).getFlag('checkout-v2', false)14 expect(flag.value).toBe(true)15 })16
17 it('returns false as default', () => {18 const flag = mock.forUser({ kind: 'user', key: 'other' }).getFlag('checkout-v2', false)19 expect(flag.value).toBe(false)20 })21})What's next
- Next.js App Router integration — full SSR + RSC pattern for Next.js deployed on Vercel.
- Cloudflare Workers integration — the same
@avsbhq/edgepattern for Cloudflare's KV. - Edge SDK reference — full
AvsbEdgeClientAPI surface.