How-to

Deploy an AI Cost Gateway in 30 Minutes on Vercel + Neon

The complete walkthrough: from zero to a running Visionality gateway with your first Spend Token, in under 30 minutes.

By Chris Therriault9 min read

This is a complete deployment walkthrough. By the end, you'll have:

  • A running Visionality gateway on Render
  • A Neon Postgres database with all 13 migrations applied
  • A Vercel-hosted operator dashboard
  • Your first Spend Token minted
  • A real API call routed through the gateway and visible in the ledger

Estimated time: 28 minutes on a clean start. 45 minutes if you're configuring PII rules and allocation rules at the same time.

Prerequisites: a Render account, a Neon account, a Vercel account, and a Clerk account. All four have free tiers that cover everything in this walkthrough.


Step 1: Fork and clone the repository (3 min)

git clone https://github.com/servicevision/AICostControl
cd AICostControl
pnpm install

All packages install. The workspace has 19 packages but pnpm handles the graph — this should take under two minutes on a decent connection.

Step 2: Provision a Neon database (5 min)

In the Neon console:

  1. Create a new project: visionality-prod (or your org name)
  2. Create a database: visionality
  3. Copy the connection string from the "Pooled connection" tab — it looks like postgres://user:[email protected]/visionality?sslmode=require
  4. Create a second role for the application: acc_app. In the Neon SQL editor:
CREATE ROLE acc_app WITH LOGIN PASSWORD 'your-strong-password';
GRANT CONNECT ON DATABASE visionality TO acc_app;

You'll use the acc_app role for the running application. The owner role runs migrations.

Step 3: Run migrations (3 min)

In your local clone, with the owner connection string:

DATABASE_URL="postgres://owner:password@.../visionality?sslmode=require" \
  pnpm --filter @acc/db migrate

This runs all 13 migrations in order. The output ends with a confirmation that append-only enforcement is in place:

✓ Migration 0001_initial complete
...
✓ Migration 0011_revoke_on_audit complete
✓ Smoke check: UPDATE privilege absent on audit_log ✓
✓ 13 migrations applied, 0 errors

The smoke check is not optional — it's the deploy-time verification that your audit tables are genuinely append-only, not just supposed to be.

Step 4: Deploy the gateway to Render (8 min)

In the Render dashboard, create a new Web Service:

  • Source: Your forked GitHub repo
  • Root directory: services/gateway
  • Build command: pnpm install && pnpm build
  • Start command: node dist/server.js
  • Instance type: Starter ($7/mo) is enough for the initial deployment

Environment variables:

DATABASE_URL=postgres://acc_app:password@.../visionality?sslmode=require
NODE_ENV=production
CLERK_SECRET_KEY=sk_live_...
ACC_VALIDATOR_HMAC=<random 32-byte base64url string>

For ACC_VALIDATOR_HMAC, generate a random value:

node -e "console.log(require('crypto').randomBytes(32).toString('base64url'))"

Deploy. The first build takes 3–4 minutes. When it's live, the health endpoint responds:

curl https://your-gateway.onrender.com/healthz
# {"status":"ok","version":"...","db":"connected"}

If db shows connected, your Neon connection is working.

Step 5: Deploy the dashboard to Vercel (5 min)

In the Vercel dashboard, import the same repo:

  • Root directory: apps/dashboard-next
  • Framework: Next.js (auto-detected)

Environment variables:

NEXT_PUBLIC_CLERK_PUBLISHABLE_KEY=pk_live_...
CLERK_SECRET_KEY=sk_live_...
DATABASE_URL=postgres://acc_app:password@.../visionality?sslmode=require
NEXT_PUBLIC_GATEWAY_URL=https://your-gateway.onrender.com

Deploy. Vercel builds Next.js fast — usually under 2 minutes. When it's done, your dashboard is live at your-project.vercel.app.

Sign in with Clerk. The first sign-in creates your operator account.

Step 6: Mint your first Spend Token (3 min)

In the dashboard, navigate to Spend Tokens → New Token.

Fill in:

  • Organization: your org name
  • Project: a project name (e.g., search-feature)
  • Allowed models: claude-3-5-haiku-20241022 (or whichever model you're testing with)
  • Spend limit: 5.00 (USD — generous for a test)
  • TTL: 24 hours

Submit. The dashboard shows:

  • Token ID: st_...
  • Validator secret: shown once, copy it now

Copy both. The validator secret is hashed and stored — you can't retrieve it again.

Step 7: Route a real request through the gateway (2 min)

With the Anthropic SDK, change one environment variable in your test application:

ANTHROPIC_BASE_URL=https://your-gateway.onrender.com

Or test directly with curl:

curl -X POST https://your-gateway.onrender.com/v1/messages \
  -H "Content-Type: application/json" \
  -H "x-api-key: your-anthropic-key" \
  -H "x-spend-token: st_..." \
  -H "x-validator: your-validator-secret" \
  -d '{
    "model": "claude-3-5-haiku-20241022",
    "max_tokens": 100,
    "messages": [{"role": "user", "content": "Say hello in one sentence."}]
  }'

The gateway intercepts the request, validates the Spend Token, reserves estimated cost, forwards to Anthropic, settles the actual cost, and returns the response.

Step 8: Verify in the dashboard (1 min)

In the dashboard, navigate to Request Explorer. Your request appears with:

  • Timestamp
  • Model used
  • Token counts (input + output)
  • Cost in USD
  • Spend token ID
  • Reserve and settle amounts

Navigate to Spend Tokens. Your token shows the remaining balance, reduced by the cost of your test request.

That's the full loop: request in → gateway validates → ledger records → dashboard shows.


Common issues

Gateway health check fails with db: disconnected Check that your DATABASE_URL uses the acc_app role, not the owner role. The owner role may have a password that contains special characters requiring URL encoding.

402 on first request Check that the model in your request matches the allowed model list in your Spend Token. Model names must be exact: claude-3-5-haiku-20241022, not claude-haiku.

Dashboard shows no data after a successful API call Check that NEXT_PUBLIC_GATEWAY_URL in your Vercel env vars points to your Render service URL without a trailing slash.

Migrations fail on step 11 Step 11 is the REVOKE migration for append-only enforcement. It requires that the acc_app role exists before the migration runs. Confirm you created the role in Step 2 before running migrations.


What's next

You have a running gateway. From here:

  • Allocation rules: In the dashboard, navigate to Settings → Allocation Rules and add a rule mapping your org/project to a GL code
  • PII policy: Navigate to Settings → PII Policy and configure your project's detection mode (block, obfuscate, or log)
  • Anomaly detection: Running automatically — check the Anomaly Inbox after a day of real traffic to see if any detectors fire

The deploy guide in the repository covers each of these in detail. For anything else, request a demo and we'll walk through it live.


Stuck on any step? Request a demo → and we'll deploy it together.

Visionality.AI

See how Visionality handles this.

30-minute demo. Live deployment. Your questions answered directly — no slides, no pitch.