Amberflo alternative: Usage Lab vs Amberflo, honestly

Amberflo is a full platform for usage metering, AI cost visibility and customer billing. Usage Lab is a small hosted metering API that keeps Stripe as your biller. Here's what each costs, where each fits, and how to move meter records across.

Every Amberflo fact below was checked on the official source linked next to it, as of Oct 23, 2026. Prices are in USD as Amberflo lists them; where Amberflo publishes no price we say "Contact sales". Usage Lab is our product; corrections are welcome at canada.site.ops@gmail.com.

Amberflo facts (as of Oct 23, 2026)

TopicFactSource
Free30-day free trial. No permanent free plan is listed.amberflo.io/pricing
Startups$99 per month: up to $10,000 billing volume and up to 10k meter events a month.amberflo.io/pricing
GrowthFrom $599 per month: up to $100,000 billing volume and up to 500k meter events a month, then 0.54% of additional billing volume and $5 per additional 10k meter events.amberflo.io/pricing
CustomCustom pricing for $1M+ billing volume a month and unlimited meter events, with SSO and role-based access: Contact sales.amberflo.io/pricing
Pricing modelUsage-based: you pay for event ingestion volume and the amount invoiced, so the cost grows with your revenue.amberflo.io/pricing
PlatformUsage metering, cost visibility and customer billing in one system: pricing plans, credits and drawdowns, invoicing and payments, a customer billing portal, alerts, and AI usage and cost guards.Amberflo docs: quick start
Meter typesCount meters (with SUM, MAX and AVG), continuous meters (start/stop duration) and seat-based meters.Meter definition
EventsMeter records carry customerId, meterApiName, meterValue, meterTimeInMillis and free-form dimensions. Ingested events can be cancelled (undo) after the fact.Meter dimensions, Meter corrections
IngestionSDKs with batching, the API, an AWS S3 bucket and an AWS CloudWatch connector. Default guardrail: 1M events per hour per meter; backfills up to 60 days.Ingestion options, Metering guardrails

Usage Lab pricing for comparison: Free CA$0 (100k events, 3 meters a month), Pro CA$12/month (2M events, 10 meters), Ultra CA$36/month (20M events, 100 meters). See pricing.

When Amberflo is the better fit

Where Usage Lab fits

Usage Lab is early access and small: no invoicing, cost tracking, credits, entitlements or SLAs.

Mapping: Amberflo meter records to Usage Lab events

AmberfloUsage LabNotes
meterApiNamemeterCreate one Usage Lab meter per Amberflo meter. A count meter you SUM maps to sum; one record per request maps to count.
customerIdsubscriptionThe customer you bill. Totals are per subscription per month.
meterValuevalueCount aggregations need no value.
meterTimeInMillistimestampDivide by 1000 for unix seconds, or send ISO 8601. Up to 30 days late is accepted.
dimensionspropertiesStored with the event, not aggregated. Split by dimension with separate meters if you price by it.
your event ididempotency_key (or the Idempotency-Key header)Required. Use your own event id, or a stable hash of the record as the sample does, so a retry counts once.
Continuous and seat-based metersno direct equivalentSend durations as a sum value, or active seats as unique_count on a user id.

Amberflo meter record (customerId, meterApiName, meterValue, meterTimeInMillis, dimensions). Input format, not a command.

{
  "customerId": "cust_af_42",
  "meterApiName": "llm-tokens",
  "meterValue": 1500,
  "meterTimeInMillis": 1790812800000,
  "dimensions": { "model": "gpt-4o-mini", "type": "input" }
}

The same event for Usage Lab (one item of POST /api/v1/usage {"events": [...]}). Not a command.

{
  "meter": "llm_tokens",
  "subscription": "cust_af_42",
  "idempotency_key": "af_<sha256 of the record, 32 hex chars>",
  "timestamp": 1790812800,
  "value": 1500,
  "properties": { "model": "gpt-4o-mini", "type": "input" }
}

This script creates the meters, converts example Amberflo records, sends them as one batch, sends the batch again to show the retry counts once, and prints this month's totals. It needs only Python's standard library and USAGE_LAB_KEY (a free key from /signup/). Save it as amberflo_to_usage_lab.py and run python3 amberflo_to_usage_lab.py.

# amberflo_to_usage_lab.py: Python 3.8+, standard library only. Needs USAGE_LAB_KEY in the environment.
# Re-sends Amberflo-style meter records to Usage Lab. Safe to re-run: each record gets a stable key.
import hashlib, json, os, sys, urllib.error, urllib.request
from datetime import datetime, timezone

API = "https://usage-lab.pages.dev/api/v1"
HEADERS = {"Authorization": "Bearer " + os.environ["USAGE_LAB_KEY"], "Content-Type": "application/json",
           "User-Agent": "usage-lab-quickstart/1.0"}  # any descriptive User-Agent; see the note below the sample

# Your Amberflo meters, re-declared: meterApiName -> (Usage Lab meter, aggregation)
METERS = {
    "llm-tokens":   ("llm_tokens",   "sum"),    # Amberflo count meter, SUM of meterValue
    "api-requests": ("api_requests", "count"),  # one record per request: count them
}

def call(method, path, body=None):
    data = None if body is None else json.dumps(body).encode()
    req = urllib.request.Request(API + path, data=data, headers=HEADERS, method=method)
    try:
        with urllib.request.urlopen(req, timeout=20) as r:
            return r.status, json.load(r)
    except urllib.error.HTTPError as e:
        return e.code, json.load(e)

def stable_key(rec):
    # Same record -> same key, so a re-send is counted once. Use your own event id here if you keep one.
    raw = json.dumps([rec["customerId"], rec["meterApiName"], rec["meterTimeInMillis"],
                      rec.get("dimensions") or {}, rec.get("seq", 0)], sort_keys=True)
    return "af_" + hashlib.sha256(raw.encode()).hexdigest()[:32]

def to_usage_lab(rec):
    meter, agg = METERS[rec["meterApiName"]]                      # meterApiName -> meter
    out = {"meter": meter,
           "subscription": rec["customerId"],                    # customerId -> subscription
           "idempotency_key": stable_key(rec),
           "timestamp": rec["meterTimeInMillis"] // 1000}         # milliseconds -> unix seconds
    if agg == "sum":
        out["value"] = float(rec["meterValue"])                   # meterValue -> value
    if rec.get("dimensions"):
        out["properties"] = rec["dimensions"]                     # dimensions -> properties
    return out

# 1. Create the meters (409 meter_exists on a re-run is fine)
for key, agg in METERS.values():
    status, body = call("POST", "/meters", {"key": key, "aggregation": agg, "name": key})
    if status not in (201, 409):
        sys.exit(f"create meter {key}: HTTP {status} {body}")

# 2. Example records, as you would have sent them to Amberflo's ingest API
now = datetime.now(timezone.utc)
month = now.strftime("%Y-%m")
ms = int(datetime(now.year, now.month, 1, tzinfo=timezone.utc).timestamp() * 1000)
amberflo_records = [
    {"customerId": "cust_af_42", "meterApiName": "llm-tokens", "meterValue": 1500,
     "meterTimeInMillis": ms, "dimensions": {"model": "gpt-4o-mini", "type": "input"}},
    {"customerId": "cust_af_42", "meterApiName": "llm-tokens", "meterValue": 620,
     "meterTimeInMillis": ms, "dimensions": {"model": "gpt-4o-mini", "type": "output"}},
    {"customerId": "cust_af_77", "meterApiName": "api-requests", "meterValue": 1,
     "meterTimeInMillis": ms, "dimensions": {"route": "/v1/search"}},
]

# 3. Send as one batch, then re-send it: the retry is counted once
batch = {"events": [to_usage_lab(r) for r in amberflo_records]}
for attempt in ("first send", "retry"):
    status, body = call("POST", "/usage", batch)
    if status >= 400:
        sys.exit(f"{attempt}: HTTP {status} {body}")
    print(attempt, body["summary"])

# 4. Read this month's totals per customer
for key in ("llm_tokens", "api_requests"):
    status, body = call("GET", f"/meters/{key}/rollups?month={month}")
    if status != 200:
        sys.exit(f"rollups {key}: HTTP {status} {body}")
    for r in body["rollups"]:
        if r["subscription"].startswith("cust_af_"):
            print(key, r["subscription"], r["quantity"])

Example output, not a command.

first send {'created': 3, 'duplicate': 0, 'conflict': 0}
retry {'created': 0, 'duplicate': 3, 'conflict': 0}
llm_tokens cust_af_42 2120
api_requests cust_af_77 1

User-Agent note: the Cloudflare edge in front of *.pages.dev rejects Python's default Python-urllib User-Agent (error 1010) before the request reaches us, so the sample sets usage-lab-quickstart/1.0. Any descriptive User-Agent works, including AI agents, bots and scripts, which are welcome.

To move history, export usage from Amberflo, feed it through to_usage_lab() in batches of up to 100, and backfill only the last 30 days. Keep invoices and older usage in Amberflo or your warehouse.

More comparisons

FAQ

How much does Amberflo cost?

As listed on amberflo.io/pricing, checked Oct 23, 2026 (USD): Startups $99 a month for up to $10,000 billing volume and 10k meter events a month; Growth from $599 a month for up to $100,000 billing volume and 500k meter events, then 0.54% of additional billing volume and $5 per additional 10k meter events; Custom pricing for $1M+ billing volume a month. Amberflo says you pay for event ingestion volume and amount invoiced.

Does Amberflo have a free plan?

Amberflo's pricing page offers a 30-day free trial. As of Oct 23, 2026 it lists no permanent free plan. (An older Amberflo blog post described a free tier; the current pricing page does not.)

What is Amberflo?

A platform for usage metering, cost visibility and customer billing: meters, pricing plans (usage-based, tiered, hybrid, credits and drawdowns), invoicing, a customer billing portal, alerts and AI cost tracking.

Can I move my Amberflo meter records to Usage Lab?

Yes. Map meterApiName to meter, customerId to subscription, meterValue to value, meterTimeInMillis divided by 1000 to timestamp, and dimensions to properties. Give each record a stable idempotency key (your own event id, or a hash of the record as in the sample) so a retry counts once. The Python sample on this page runs as-is.

Do AI agents and bots count as real usage?

Yes. In Usage Lab, usage you send from AI agents, bots and scripts is real, billable usage and is counted like any other event. We never block or filter agent traffic; any descriptive User-Agent works.

When should I stay on Amberflo?

When you want one platform for metering, pricing plans, invoicing, prepaid credits, a customer billing portal and AI cost and margin tracking, or you need high ingestion limits, S3 or CloudWatch ingestion, and enterprise SLAs. Usage Lab only meters usage and leaves billing to Stripe.

What does Usage Lab cost?

Free: CA$0 for 100,000 events and 3 meters a month. Pro: CA$12 a month for 2M events and 10 meters. Ultra: CA$36 a month for 20M events and 100 meters. Flat prices, never a percentage of your billings.