n4nAI

Configuring environment variables for edge AI SDK functions

Configure environment variables for Vercel AI SDK edge functions with step-by-step instructions for local development, preview deployments, and production.

n4n Team4 min read812 words

Audio narration

Coming soon — every post will get a voice note here.

Environment variables are the backbone of any production edge functions vercel ai sdk environment variables setup. They separate credentials from code, enable per-environment tuning, and keep your API keys out of version control. This guide walks through the complete lifecycle: local development with .env.local, preview deployments via Vercel CLI, production configuration in the dashboard, and runtime validation so you catch misconfiguration before it hits users.

Step 1: Define the contract with a schema

Before adding any values, codify what your edge function expects. A Zod schema gives you parse-time safety and self-documenting errors.

// lib/env.ts
import { z } from "zod";

export const edgeEnvSchema = z.object({
  OPENAI_API_KEY: z.string().min(1, "OpenAI API key is required"),
  ANTHROPIC_API_KEY: z.string().optional(),
  DEFAULT_MODEL: z.string().default("gpt-4o-mini"),
  MAX_TOKENS: z.coerce.number().int().positive().default(4096),
  TEMPERATURE: z.coerce.number().min(0).max(2).default(0.7),
  LOG_LEVEL: z.enum(["debug", "info", "warn", "error"]).default("info"),
  RATE_LIMIT_RPM: z.coerce.number().int().positive().default(60),
});

export type EdgeEnv = z.infer<typeof edgeEnvSchema>;

Why Zod over plain process.env checks: You get a single source of truth, automatic coercion for numeric flags, and a clear error message when MAX_TOKENS="unlimited" slips through.

Step 2: Create local development files

Vercel respects .env.local for vercel dev and ignores it in .gitignore by default. Create the file at your repository root:

# .env.local
OPENAI_API_KEY=sk-proj-abc123...
ANTHROPIC_API_KEY=sk-ant-api03-xyz789...
DEFAULT_MODEL=gpt-4o-mini
MAX_TOKENS=4096
TEMPERATURE=0.7
LOG_LEVEL=debug
RATE_LIMIT_RPM=120

Add .env.local to .gitignore if it isn’t already:

# .gitignore
.env.local
.env*.local

Verification: Run vercel dev and confirm the function starts without schema validation errors. You should see your LOG_LEVEL=debug output in the console.

Step 3: Load and validate at runtime

Edge functions run in a constrained V8 isolate — no fs access, no require.cache. Load once at module initialization, not per-request.

// lib/env.ts (continued)
let cachedEnv: EdgeEnv | null = null;

export function getEdgeEnv(): EdgeEnv {
  if (cachedEnv) return cachedEnv;

  const parsed = edgeEnvSchema.safeParse(process.env);
  if (!parsed.success) {
    const messages = parsed.error.errors.map(e => `${e.path.join(".")}: ${e.message}`).join("; ");
    throw new Error(`Invalid environment configuration: ${messages}`);
  }

  cachedEnv = parsed.data;
  return cachedEnv;
}

Use it in your route handler:

// app/api/chat/route.ts
import { streamText } from "ai";
import { openai } from "@ai-sdk/openai";
import { getEdgeEnv } from "@/lib/env";

export const runtime = "edge";

export async function POST(req: Request) {
  const env = getEdgeEnv();
  const { messages } = await req.json();

  const result = await streamText({
    model: openai(env.DEFAULT_MODEL),
    messages,
    maxTokens: env.MAX_TOKENS,
    temperature: env.TEMPERATURE,
  });

  return result.toDataStreamResponse();
}

Verification: Hit the endpoint with curl -X POST http://localhost:3000/api/chat -d '{"messages":[{"role":"user","content":"ping"}]}' -H "Content-Type: application/json" and confirm a streaming response.

Step 4: Configure preview deployments via CLI

Every git push to a non-main branch creates a preview deployment. Set its environment variables without touching the dashboard:

# Pull current preview env (optional, for inspection)
vercel env ls --scope=<team-slug> --environment=preview

# Add or update a secret for preview
vercel env add OPENAI_API_KEY preview --scope=<team-slug>
# Enter value when prompted: sk-proj-preview-key...

# Bulk upsert from a file (useful for CI)
vercel env pull .env.preview --environment=preview --scope=<team-slug>
# Edit .env.preview, then:
vercel env push .env.preview --environment=preview --scope=<team-slug>

Key distinction: vercel env add prompts interactively. vercel env push reads KEY=VALUE lines from a file — ideal for scripted CI jobs.

Verification: Open the preview URL, hit the chat endpoint, and verify the response uses the preview model (check logs for DEFAULT_MODEL value).

Step 5: Set production variables in the dashboard

Production values live in Vercel Dashboard → Project → Settings → Environment Variables. Use the UI for secrets you never want in CLI history.

  1. Click Add New.
  2. Key: OPENAI_API_KEY, Value: your production key, Environment: Production only.
  3. Repeat for ANTHROPIC_API_KEY, DEFAULT_MODEL=gpt-4o, MAX_TOKENS=8192, LOG_LEVEL=warn, RATE_LIMIT_RPM=300.
  4. Save. Vercel triggers a new production deployment automatically.

Verification: Check the deployment log for “Environment Variables: 6 applied”. Call the production endpoint and confirm LOG_LEVEL=warn suppresses debug output.

Step 6: Handle runtime-specific quirks

Edge runtime differs from Node.js in ways that bite environment variable handling:

Constraint Workaround
No process.env mutation Treat env as read-only; derive computed values in getEdgeEnv()
No dotenv package Rely on Vercel’s built-in injection; don’t import dotenv
1 MB bundle limit Keep schema and validation lean; avoid heavy deps
No crypto module (older isolates) Use Web Crypto API (crypto.subtle) for any key derivation

If you need a derived value — say, a hashed API key for logging — compute it inside the getter:

// lib/env.ts (addition)
import { createHash } from "node:crypto"; // available in edge runtime

function hashKey(key: string): string {
  return createHash("sha256").update(key).digest("hex").slice(0, 8);
}

export function getEdgeEnv(): EdgeEnv {
  // ... existing parse logic ...
  return {
    ...cachedEnv,
    OPENAI_API_KEY_HASH: hashKey(cachedEnv.OPENAI_API_KEY),
  } as EdgeEnv & { OPENAI_API_KEY_HASH: string };
}

Step 7: Validate in CI before deploy

Fail fast. Add a GitHub Actions step that runs the schema against the preview environment file.

# .github/workflows/validate-env.yml
name: Validate environment variables
on:
  pull_request:
    paths:
      - ".env.preview"
      - "lib/env.ts"

jobs:
  validate:
    runs-on: ubuntu-latest
    steps:
      - uses: actions/checkout@v4
      - uses: actions/setup-node@v4
        with:
          node-version: "20"
      - run: npm ci
      - run: npx tsx -e "
          import { edgeEnvSchema } from './lib/env';
          import { config } from 'dotenv';
          config({ path: '.env.preview' });
          const result = edgeEnvSchema.safeParse(process.env);
          if (!result.success) {
            console.error(result.error.format());
            process.exit(1);
          }
          console.log('Environment validation passed');
        "

Verification: Open a PR with a malformed .env.preview (e.g., MAX_TOKENS=high) and watch the check fail with a clear Zod error.

Step 8: Rotate secrets without downtime

Vercel applies environment variable changes on the next deployment. For zero-downtime rotation:

  1. Add the new key with a suffix: OPENAI_API_KEY_NEW.
  2. Deploy a version of your function that reads process.env.OPENAI_API_KEY_NEW ?? process.env.OPENAI_API_KEY.
  3. Verify the new key works in preview.
  4. Promote to production.
  5. Remove the old key from the dashboard.
  6. Deploy again to drop the fallback.
// Temporary rotation shim
function getActiveOpenAIKey(): string {
  return process.env.OPENAI_API_KEY_NEW ?? process.env.OPENAI_API_KEY;
}

Verification: Monitor error rates during the overlap window. Zero 401s from the provider means rotation succeeded.

Step 9: Debug missing or wrong values in production

When a production function misbehaves, check three places in order:

  1. Vercel Dashboard → Functions → View Function Logs — look for the schema validation error thrown at module load.
  2. Runtime logs — search for Invalid environment configuration.
  3. Edge network tab — confirm the deployed function bundle includes your env validation code (it should, since it runs at import time).

Common failure modes:

Symptom Cause Fix
OPENAI_API_KEY: Required in logs Variable not set for Production environment Add in Dashboard → Settings → Environment Variables
MAX_TOKENS: Expected number, received nan Value set to empty string Set explicit numeric value
Function works locally but fails on preview Preview env missing variable vercel env add KEY preview
TypeScript error: Property 'OPENAI_API_KEY_HASH' does not exist Type definition out of sync Regenerate types or cast in getter

Step 10: Optional — integrate with external secret stores

For teams requiring audit trails, rotation policies, or shared secrets across projects, pull values at build time from 1Password, AWS Secrets Manager, or HashiCorp Vault. Example with 1Password CLI:

# .github/workflows/deploy.yml (excerpt)
- name: Load secrets from 1Password
  uses: 1password/load-secrets-action@v1
  with:
    env-file: ".env.production.generated"
  env:
    OP_SERVICE_ACCOUNT_TOKEN: ${{ secrets.OP_SERVICE_ACCOUNT_TOKEN }}

- name: Push to Vercel production
  run: vercel env push .env.production.generated --environment=production --scope=$VERCEL_SCOPE --token=$VERCEL_TOKEN

The generated file contains only KEY=VALUE lines — no schema, no comments. Your getEdgeEnv() still validates on startup.

Verification: Confirm the generated file exists in the workflow artifacts (masked), and the subsequent deployment shows the expected variable count.


You now have a complete, auditable pipeline: schema-defined contract, local override, preview isolation, production hardening, CI validation, and zero-downtime rotation. The same pattern scales to any edge functions vercel ai sdk environment variables configuration — add keys to the schema, push to the appropriate environment, and the runtime validation catches drift before users do.

Tagsvercel-ai-sdkedge-functionsenvironment-variablesconfiguration

Written by

n4n Team

The team building n4n — a single OpenAI-compatible API in front of 240+ models, with automatic fallback, load balancing and pay-per-token metering.

More from n4n Team →

All vercel ai sdk on edge & serverless runtimes posts →