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
, sumai-token
, uniqueevent_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 orfiltered_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 daysABSOLUTE
— explicit start and endALL
— 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
ofapi-call
. - AI tokens → simple metric:
SUM
ofeventValue
onai-token
. - Monthly active users → SQL metric:
SELECT COUNT(DISTINCT customer_id) FROM filtered_events WHERE event_name = 'user-login'
.
- API requests → simple metric:
- 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
- Model what you sell: Modeling Features
- Send usage data: Events
- Design pricing: Plans & Pricing
- Control access: Entitlements
- Troubleshoot patterns: Troubleshooting & Patterns