Sign in →
Getting Started1 min read

Environments: Sandbox vs Production

Understand the difference between Aforo sandbox and production environments — key prefixes, data isolation, and how to switch safely.

Updated 2026-06-15Suggest edits
Docs Getting Started Environments

Aforo runs two fully isolated environments — Sandbox and Production. They share no data, no customer records, and no billing state. The environment is determined entirely by which API key you use — no configuration flag, no environment header, no separate base URL to manage.

Sandbox Environment#

The sandbox is a full-fidelity replica of production. Every feature — metering, entitlements, margin guards, rate plans, invoicing — works identically. The only difference is that no real charges are generated. It is safe to fire any event, create any customer, or simulate any billing scenario without financial consequence.

Key prefix
sk_test_…
Billing
No charges ever
Ingest endpoint
ingest-sandbox.aforo.ai
Dashboard
Aforo Dashboard (Sandbox tab)
Rate limits
10,000 events/hour (generous for testing)
Data retention
30 days (production: 2 years)
PRO TIP
Use the sandbox to validate your integration end-to-end before going live. Fire 10,000 events, simulate quota exhaustion, test overage behavior, and verify your dashboard alerts — all without touching real customer data or generating invoices.

What the Sandbox Simulates Accurately

The sandbox is not a mock. It runs the same metering pipeline, the same rating engine, and the same entitlement cache as production. The following behaviors are identical in both environments:

Event ingestion and deduplication
Rate plan calculation (all 6 pricing models)
Entitlement checks and quota enforcement
Margin guard thresholds and interventions
Webhook delivery and retry logic
Invoice generation and credit note flow
Subscription state machine transitions
SDK batch buffering and flush behavior
Gateway plugin metering (if deployed)

Production Environment#

The production environment processes real usage events that generate real charges on real customer invoices. Every event is rated against your live rate plans, accrues to the customer's invoice ledger, and is included in the next billing cycle.

Key prefix
sk_live_…
Billing
Real charges — customers are invoiced
Ingest endpoint
ingest.aforo.ai
Dashboard
Aforo Dashboard (Production tab)
Rate limits
Per your contract (default 1M events/hour)
Data retention
2 years (sandbox: 30 days)
WARNING
Never run load tests or integration tests against the production environment. Every event sent with a sk_live_ key is billed. A test suite that fires 50,000 events will generate 50,000 billable events on your customers' accounts.

Switching Environments#

Switching between environments requires only changing the AFORO_API_KEY environment variable. No code changes. No config file updates. No redeployment of your application logic — only the secrets layer changes.

.env.development
# Sandbox — safe for local dev and CI
AFORO_API_KEY=sk_test_a1b2c3d4e5f6g7h8i9j0k1l2m3n4o5p6q7r8s9t0
AFORO_PRODUCT_ID=prod_sandbox_abc123
.env.production
# Production — real billing, handle with care
AFORO_API_KEY=sk_live_x9y8z7w6v5u4t3s2r1q0p9o8n7m6l5k4j3i2h1
AFORO_PRODUCT_ID=prod_live_xyz789

The SDK and all gateway plugins inspect the key prefix at startup and route to the correct ingest endpoint automatically. You do not need to set a separate AFORO_INGEST_URL — that is handled for you.

The SDK handles endpoint routing automatically
import { AforoClient } from '@aforo/metering';

const aforo = new AforoClient({
  apiKey: process.env.AFORO_API_KEY!,
  // No ingestUrl needed — SDK reads the key prefix:
  //   sk_test_ → ingest-sandbox.aforo.ai
  //   sk_live_ → ingest.aforo.ai
});

// This works identically in sandbox and production.
// The key determines where events go.
await aforo.meter({ customerId: 'cust_123', metricId: 'api_calls', quantity: 1 });
INFO
If you need to override the ingest URL (e.g. for on-premise deployments), you can set ingestUrl explicitly in the SDK constructor. In that case, the automatic prefix-based routing is bypassed and your URL is used directly.

Environment Variables#

The following environment variables are recognised by Aforo SDKs and gateway plugins. All are optional except AFORO_API_KEY.

VariableRequiredDefaultDescription
AFORO_API_KEYrequiredYour sk_test_ or sk_live_ API key
AFORO_PRODUCT_IDoptionalKey defaultProduct scope. Set if your key covers multiple products.
AFORO_INGEST_URLoptionalAuto (from prefix)Override ingest endpoint. Use for on-premise or custom routing.
AFORO_BATCH_SIZEoptional100Max events per flush batch.
AFORO_FLUSH_INTERVAL_MSoptional5000Max milliseconds between automatic flushes.
AFORO_DEBUGoptionalfalseSet to true to log all outbound events to stdout.

Multi-Environment CI Setup

For CI/CD pipelines that deploy to multiple environments, inject the correct 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_SANDBOX_KEY }}  # sk_test_...

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

Data Isolation#

Sandbox and production environments are fully isolated at the infrastructure level. They run on separate database, cache, streaming, and analytics infrastructure. There is no shared state and no data cross-contamination possible.

SANDBOX BOUNDARY
Customers created in sandbox are sandbox-only
Rate plans and offerings are independent copies
Events appear only in sandbox Event Log
Invoices are simulated — never sent to payment processor
Webhooks fire to your sandbox webhook endpoints
Data purged after 30 days
PRODUCTION BOUNDARY
Real customer records with billing history
Live rate plans that generate revenue
Events feed real invoices and revenue reports
Invoices charged via connected payment processor
Webhooks fire to your production webhook endpoints
Data retained for 2 years for compliance
PRO TIP
When building your integration, start in sandbox with a customer ID like cust_test_001. When you go live, create the real customer in production. There is no migration or data-copy tool — sandbox data is intentionally throwaway.

Sandbox Dashboard

The Aforo Admin Panel shows sandbox and production data in separate tabs. Events fired with a sk_test_ key appear only in the Sandbox tab and are never visible in the Production tab — even if the customer ID happens to match a real production customer. The environment boundary is enforced server-side by the key, not by the dashboard UI.

Dashboard navigation
Aforo Dashboard
├── [Sandbox]     ← Events from sk_test_ keys appear here
│   ├── Event Log
│   ├── Customers
│   └── Invoices (simulated — no real charges)
│
└── [Production]  ← Events from sk_live_ keys appear here
    ├── Event Log
    ├── Customers
    └── Invoices (real — billed to payment processor)