Luau classify context
When a plan defines classify = function(ctx) ... end, the engine calls it after JSON classify and limits (if configured), and before committing each usage event (POST /usage, StatsD, usage.recorded). Pipeline: Plan extensions → ingest.
When classify(ctx) runs
Only when the user has an active subscription on a plan whose Luau script defines classify. The engine runs classify(ctx), then records usage with the
(possibly rerouted) metric. Errors and timeouts reject the usage event (HTTP 400).
Your app can keep sending one metric code (for example tokens or api_requests) — classify decides which plan meter actually receives the event.
Examples
Peak / off-peak meters
An LLM API records a single tokens counter from the SDK. The plan defines separate
meters for business hours and nights/weekends, each with its own included allowance. Classify
reroutes by ctx.hour (UTC).
Hard cap at ingest
A free plan includes 100 API requests per billing period. Instead of letting usage accumulate and
billing overage later, classify rejects the request as soon as month_used + quantity would exceed the cap — your app gets 400 and can show an upgrade prompt immediately.
Bulk vs standard routing
Batch jobs send the same api_requests metric as interactive traffic, but large payloads
(500+ units per event) should bill under a cheaper bulk meter. Classify inspects ctx.quantity on each event.
Fields
| Field | Type | Description |
|---|---|---|
user_id | string | User recording usage |
metric_code | string | Submitted metric code |
quantity | integer | Units in this event |
plan_code | string | Active plan for this user |
period_used | integer | Usage on the current metric (or its group) in the billing period before this event |
source | string | http, statsd, or system |
month_used | integer | Total usage across all plan metrics in the current billing period, recorded before this event — useful for caps |
occurred_at | RFC3339 | Event timestamp |
hour | integer | Hour of day in UTC (0–23) |
weekday | integer | Day of week UTC (0 = Sunday) |
hour_local | integer | Hour in the user's billing timezone (0–23) |
weekday_local | integer | Day of week in the user's billing timezone |
month / day_of_month | integer | UTC calendar month (1–12) and day of month (1–31) |
month_local / day_of_month_local | integer | Same fields in the user's billing timezone |
JSON classify.routes supports the same calendar, quantity, period-usage, and source
predicates without Luau — see Plan extensions → JSON classify.
Return value
classify(ctx) must return a table:
{ metric_code = "..." }— keep or override the target metric (must exist on the plan){ allow = false, reason = "..." }— reject usage{}or omittedmetric_code— keep the submitted metric
See Pricing → Limits for timeout and script size constraints.