Features, Metrics & Events

Metrics

Metrics turn events into billable or limitable numbers. Pricing uses them to compute charges, and entitlement checks use them to compare usage against credits.

Choosing a metric type

  • simple — built-in aggregations over a single event name

    • Use for counts, sums, mins/maxes, averages, unique counts
    • Examples: count api-call, sum ai-token, unique event_string for MAU
  • indexed — SQL over a prefiltered CTE named filtered_events

    • Use when you need filters, joins via CTEs, or DISTINCT over properties
    • Example: active users by cohort, filtered by properties.region
  • complex — same as indexed with fewer restrictions

    • Use for advanced queries that don’t fit the indexed rules

Pick the simplest type that answers the question. Simpler metrics are easier to maintain and faster to evaluate.

Map your events to metrics

Minimal shapes (trimmed for clarity):

{
  "simple": {
    "name": "API calls",
    "queryType": "simple",
    "aggregationType": "COUNT",
    "eventName": "api-call",
    "valueType": "NUMERIC"
  },
  "sql": {
    "name": "Monthly active users",
    "queryType": "indexed",
    "sqlDefinition": "SELECT COUNT(DISTINCT event_string) AS value FROM filtered_events WHERE event_name = 'user-login'"
  }
}

Guidelines:

  • Keep event names stable and descriptive
  • For DISTINCT-style questions, prefer SQL metrics
  • Avoid overcomplicated SQL when a simple metric will do

Writing SQL metrics safely

SQL metrics must be SELECT-only and read from filtered_events. Lumen injects timeframe, merchant, and customer filters for you.

Allowed patterns:

  • Common functions: count, sum, avg, min, max, date_trunc, extract, coalesce
  • CTEs via WITH are supported; reference only CTEs or filtered_events

Example:

WITH us AS (
  SELECT * FROM filtered_events WHERE properties->>'region' = 'us-east-1'
)
SELECT COUNT(*) AS value FROM us WHERE event_name = 'api-call';

Timeframes and testing

Metrics accept a timeframe when you fetch their value:

  • RELATIVE — last N days
  • ABSOLUTE — explicit start and end
  • ALL — entire history

Quick check (trimmed):

curl "$API_URL/v1/metrics/met_x/value?customerId=cus_123&timeframe=%7B%22type%22%3A%22RELATIVE%22%2C%22days%22%3A30%7D" -H "Authorization: Bearer $LUMEN_SECRET_KEY"

Linking to features

Attach metrics to numeric features so entitlement checks can compare usage to credits. When the feature is usage_based, usage comes from its linked metrics.

Practices that age well

  • Mappings:
    • API requests → simple metric: COUNT of api-call.
    • AI tokens → simple metric: SUM of eventValue on ai-token.
    • Monthly active users → SQL metric: SELECT COUNT(DISTINCT customer_id) FROM filtered_events WHERE event_name = 'user-login'.
  • Simplicity: Start with simple metrics and introduce SQL only when needed for complex filters or joins.
  • Reuse: Reuse the same metric across different pricing models and for entitlement checks.
  • Versioning: If you must change a metric’s core logic, create a new one (e.g., api-calls-v2) to avoid affecting historical data.

See also