/Docs

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

1

Install

terminal
bash
1npm install @avsbhq/node @avsbhq/utils
2

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

3

Bootstrap the server SDK

Declare the AvsbServer instance outside the handler so it is reused across warm invocations.

api/flags.ts
typescript
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}
4

Read a flag

typescript
1const flag = avsb.getFlag('checkout-v2', false)
2// flag.value — the typed boolean result
3// flag.source — 'rule' | 'default' | 'not_found' | ...
4// flag.variationKey — which variation was served
5

Track an event

typescript
1avsb.track('checkout_started', {
2 value: 149.99,
3 properties: { currency: 'usd' },
4})
6

Identify a user

Pass full user attributes when building the scoped client. You can include any targeting attributes your flag rules depend on.

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

1

Install

terminal
bash
1npm install @avsbhq/edge @vercel/edge-config
2

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

3

Bootstrap the edge client

api/edge-flag.ts
typescript
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 ?? null
15 },
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}
Datafile refresh
Edge Functions cannot run background timers. Keep the Edge Config entry fresh by creating a webhook in your A vs B project (Settings → Webhooks) that fires on datafile.published and writes the new datafile JSON to your Edge Config store via the Vercel Edge Config API.
4

Read a flag

typescript
1const flag = scoped.getFlag('new-banner', false)
2// flag.value — boolean result
3// flag.source — 'rule' | 'default' | 'not_found'
5

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.

typescript
1import { waitUntil } from '@vercel/functions'
2
3scoped.track('banner_clicked', { value: 1 })
4
5// Flush after response — does not delay the response
6waitUntil(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

api/flags.test.ts
typescript
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