Skip to Content
Living documentation — last reviewed 2026-05-28
FeaturesInsightsInsights — Data Model

Insights — Data Model

Insights are a derived view — no dedicated table. They read from:

Source tableUsed forKey columns
cancellation_requestsfinance.cancellation_requestsorganization_id, status
subscriptionsfinance.cancellation_requests, finance.outstanding_debt, members.at_risk_billingmembership_id, status, debt_amount_in_cents, cancel_at_period_end, deleted_at
membershipsAll rulesorganization_id, role, deleted_at
usersmembers.at_risk_billing samplefirst_name, last_name, email
tasksoperations.tasks_overdueorganization_id, due_date, status enum

Response payload

interface Insight { id: InsightId; // i18n key + telemetry tag category: InsightCategory; // 'finance' | 'members' | 'operations' severity: InsightSeverity; // 'info' | 'warning' | 'urgent' count: number; // primary metric drilldownHref: string; // deep link with query params meta?: Record<string, unknown>; // per-rule extra context }

Meta shapes

  • finance.cancellation_requests{ pending: number; scheduled: number }.
  • finance.outstanding_debt{ totalDebtInCents: number; members: number }.
  • members.at_risk_billing{ sample: Array<{ membershipId: string; name: string | null; email: string }> }.
  • operations.tasks_overdue{ ... } (see service for current shape).

Index dependencies

The rules assume the following indexes exist (set by their respective domain schemas):

  • memberships(organization_id, role).
  • subscriptions(membership_id, status, deleted_at).
  • cancellation_requests(organization_id, status).
  • tasks(organization_id, due_date).

If any of these are dropped, the insights endpoint will slow proportionally — there’s no fallback path.

Locale

Server is locale-agnostic. The frontend localizes by id against the dictionary; new locales need new i18n keys, not new server code.