v2_3_<object>, grouped below by lane. The one exception is events: the event log is immutable and unversioned, delivered as events (not v2_3_events) β see Events.
Type legend
Types below are engine-neutral. How each engine surfaces them:- Timestamps are epoch-milliseconds (
number (epoch ms)), not native datetimes β convert before use. See Querying β Timestamps. The one exception isevents.timestamp, which is a realtimestamp. - JSON columns are stored as strings β parse them with
JSONExtract*(ClickHouse) orJSON_VALUE(BigQuery).
Keys
- β marks the stable, immutable key for a table β join and filter on this.
- π marks a stable foreign key (
internal_customer_id,internal_feature_id,internal_product_id,internal_entity_id,internal_reward_id) β join to the matchinginternal_id. - External ids (
customer_id,plan_id,feature_id,entity_id,id, β¦) are mutable β convenient for display, but donβt rely on them as stable keys. See Querying β Use internal ids. org_idis your tenant id (constant across your tables);envissandboxorlive(notproductionβ filteringenv = 'production'silently returns zero rows).
Catalog
Your pricing model: features, plans, plan items, rewards, and referral programs.v2_3_features β feature catalog
v2_3_features β feature catalog
v2_3_plans β plan headers with base pricing
v2_3_plans β plan headers with base pricing
v2_3_plan_items β entitlements + linked prices
v2_3_plan_items β entitlements + linked prices
v2_3_rewards β discounts, free products, promos
v2_3_rewards β discounts, free products, promos
v2_3_referral_programs β referral configuration
v2_3_referral_programs β referral configuration
Subjects
Who your plans apply to: customers and entities (sub-customers).v2_3_customers β customer master record
v2_3_customers β customer master record
v2_3_entities β sub-customers scoped to a feature
v2_3_entities β sub-customers scoped to a feature
States
Active customerβproduct relationships: recurring subscriptions and one-off purchases.v2_3_subscriptions β recurring customer products
v2_3_subscriptions β recurring customer products
v2_3_purchases β one-off purchases
v2_3_purchases β one-off purchases
Balances
Feature balances, their per-entitlement breakdowns, rollover grants, and boolean feature flags.entity_id is the scope of the row: null means customer-scoped (pooled), non-null means the row belongs to that entity. In v2_3_balances and v2_3_breakdowns a given entitlement appears exactly once, under whichever scope it holds β the two kinds of row are disjoint, so filtering to coalesce(entity_id, '') = '' gives you customer-scoped rows only, and dropping entity-scoped ones. v2_3_flags is the exception: an entity-scoped flag is emitted twice, once at its own entity scope and once into the customer pool, so keep the pooled rows there to avoid double counting. (In ClickHouse use coalesce, not entity_id IS NULL β IS NULL throws on these Iceberg columns; BigQuery is unaffected. See Querying β Pooled vs per-entity.)v2_3_balances β aggregated balance per customer Γ feature Γ entity
v2_3_balances β aggregated balance per customer Γ feature Γ entity
v2_3_breakdowns β per-entitlement balance detail
v2_3_breakdowns β per-entitlement balance detail
customer_entitlement β internal_id alone is the key. (It used to be (internal_id, entity_id), because one entitlement could emit a pooled row plus per-entity rows. That fan-out is gone; entity_id is now simply the scope this single row belongs to.)v2_3_rollovers β rollover grants carried across reset cycles
v2_3_rollovers β rollover grants carried across reset cycles
v2_3_balances or v2_3_breakdowns includes these amounts β you add them by joining internal_breakdown_id back to v2_3_breakdowns.internal_id.Rollovers are a separate table rather than extra columns on v2_3_breakdowns because they are sparse: roughly 6.8% of customer entitlements carry one (about 7.8M rollovers against 115M entitlements). Folding them in would put mostly-null columns on every breakdown row, so the ~93% of rows with no rollover would pay for the 7% that do. One entitlement can also hold several grants with different expiries, which a flat column set canβt represent at all.entity_id column β per-entity rollover amounts are left packed in the entities JSON map rather than exploded into rows. Parse it if you need entity-level rollover detail.v2_3_flags β boolean feature flags
v2_3_flags β boolean feature flags
subscription_ids array was dropped β use subscription_ids_csv, which every engine handles identically; split on , if you need the individual ids.Invoices
Invoices and their line items.v2_3_invoices β invoice master record
v2_3_invoices β invoice master record
v2_3_invoice_line_items β invoice line detail
v2_3_invoice_line_items β invoice line detail
Events
The append-only usage event log. This is the highest-volume table and is append-only (no updates).events β usage event log
events β usage event log
events.timestamp is a native timestamp β no epoch-ms conversion needed. created_at is still epoch-ms.