Sign in →
1 min read

Environments: Test vs Production

How Aforo separates test from production usage — the key prefix decides the environment, and a dedicated test endpoint guarantees non-billable events.

Updated 2026-07-29Suggest edits

Two environments, one key#

Aforo separates test from production by the API key you use — not by a config flag, an environment header, or a separate base URL. A sk_test_ key marks the test environment; a sk_live_ key marks production. Both post to the same ingest host, ingest.aforo.ai; the key decides which environment the event lands in.

INFO
There is no ingest-sandbox.aforo.ai and no prefix-based host switching. Everything goes to ingest.aforo.ai. To move between environments you swap the key — nothing else changes.

The test environment#

Use a sk_test_ key for local development, CI, and integration tests. It runs the same metering, entitlement, and rating pipeline as production, so your integration behaves the same way — but keeps test traffic separate from your live data.

Guaranteed non-billable: POST /v1/ingest/test

When you just want to confirm connectivity without touching any of your own data, post to the dedicated test endpoint. It routes the event to Aforo's own sandbox workspace regardless of the key you present, so it never bills and never appears under your workspace. It also skips metric-existence validation — any metric name is accepted for a smoke test.

curl — non-billable connectivity check
curl -X POST https://ingest.aforo.ai/v1/ingest/test \
  -H "Authorization: Bearer sk_test_YOUR_KEY_HERE" \
  -H "Content-Type: application/json" \
  -d '{
    "customerId": "cust_test_001",
    "metricName": "api_calls",
    "quantity": 1
  }'

The regular POST /v1/ingest path behaves identically in both environments — the difference is which key you send.

Production#

A sk_live_ key processes real usage: every event is rated against your live rate plans and accrues to the customer's invoice for the next billing cycle.

WARNING
Never run load or integration tests with a sk_live_ key. A suite that fires 50,000 events writes 50,000 events into your production data. Use a sk_test_ key — and /v1/ingest/test for pure connectivity checks.

Switching environments#

Switching is a one-line change: point AFORO_API_KEY at the other key. No code changes, no config files, no redeploy of your application logic — only the secret changes.

.env.development
# Test — safe for local dev and CI
AFORO_API_KEY=sk_test_a1b2c3d4e5f6a7b8c9d0e1f2a3b4c5d6
.env.production
# Production — real billing, handle with care
AFORO_API_KEY=sk_live_f6e5d4c3b2a1f0e9d8c7b6a5f4e3d2c1

You read the variable and pass it to the client — the SDK doesn't read the environment for you, and it doesn't inspect the key prefix to pick a host. There is one default host (ingest.aforo.ai), which you can override with baseUrl for on-premise or proxied deployments.

Node.js — @aforo/metering
import { AforoClient } from '@aforo/metering';

const aforo = new AforoClient({
  apiKey: process.env.AFORO_API_KEY!,   // you read it and pass it in
  // baseUrl: 'https://ingest.internal',  // optional — override the default host
});

// The key determines the environment. Same call in test and production:
await aforo.track({ customerId: 'cust_123', metricName: 'api_calls', quantity: 1 });

SDK options#

These are constructor options, not environment variables — the client reads none of these from the environment automatically. Read what you need from your own env and pass it in.

OptionRequiredDefaultDescription
apiKeyrequired—Your sk_test_ or sk_live_ key. Determines the environment.
baseUrloptionalhttps://ingest.aforo.aiOverride the ingest host — on-premise, a proxy, or a private endpoint.
flushCountoptional50Buffered events before an automatic flush.
flushIntervaloptional5000Max milliseconds between automatic flushes.

Per-environment keys in CI

Inject the right key per environment via your CI provider's secrets:

.github/workflows/deploy.yml (example)
jobs:
  deploy-staging:
    environment: staging
    steps:
      - run: npm run deploy
        env:
          AFORO_API_KEY: ${{ secrets.AFORO_TEST_KEY }}   # sk_test_...

  deploy-production:
    environment: production
    steps:
      - run: npm run deploy
        env:
          AFORO_API_KEY: ${{ secrets.AFORO_LIVE_KEY }}   # sk_live_...

Keeping test data out of production#

The environment boundary is enforced server-side by the key, not by the UI. Events sent with a sk_test_ key are scoped to your test data and are never mixed into your production billing — even if a customer ID happens to match a real production customer. And anything sent to /v1/ingest/test lands in Aforo's sandbox workspace, entirely outside your account.

INFO
Test data is throwaway — there is no migration or copy tool from test to production. Build against a test key with an ID like cust_test_001, then create the real customer in production when you go live.