offdataai
SaaS & Technology · data model template

SaaS Subscription Analytics data model

Kimball warehouse for SaaS metrics: the canonical per-account monthly MRR snapshot tagged with movement category, an accumulating subscription snapshot, product usage events, invoices/payments, and support tickets.

Subscription-business analytics for a B2B SaaS: monthly recurring revenue movement (new / expansion / contraction / churn), product usage, billing, and support — modeled as a Kimball star schema so MRR, ARR, NRR, retention cohorts, and product engagement all share conformed account, user, plan, and date dimensions. It is a Kimball dimensional model: fact tables at a declared grain surrounded by conformed dimensions, ready for BI tools and a semantic layer.

KimballSaaS & TechnologySOC2GDPR
14
tables
124
columns
21
relationships
4
PII columns

Opening the template creates a project with the ERD, platform-native DDL, a dbt project and documentation already generated (recommended platform: BigQuery). Edit it in plain English or on the canvas, then ship it to any supported warehouse.

Subject areas

revenueproductsupportconformed_dimensions

Design decisions

  • Per-account monthly MRR snapshot with change category

    The standard way to compute MRR/ARR movement and NRR is one row per account per month classified as new/expansion/contraction/churn.

  • Accumulating snapshot for subscription lifecycle

    Subscriptions have milestone dates (trial end, start, cancel) best modeled as an accumulating snapshot updated in place.

Tables in the SaaS Subscription Analytics model

Every table with its grain, columns, types and keys. PK marks a primary key, BK a business key and PII a column classified as personal data, which gets a masking strategy by default.

Fact tables (6)

fct_subscription

Grain: one row per subscription (accumulating snapshot)

Accumulating snapshot — milestones update in place.

ColumnTypeKeys
subscription_keybigintPK
account_keybigint
plan_keybigint
status_keybigint
start_date_keybigint
end_date_keybigint
trial_end_date_keybigint
subscription_numbervarchar
seatsinteger
mrrdecimal
arrdecimal
billing_periodvarchar
is_activeboolean

fct_mrr_snapshot

Grain: one row per account per month (periodic snapshot)

The canonical SaaS MRR-movement snapshot.

ColumnTypeKeys
date_keybigint
account_keybigint
plan_keybigint
mrr_change_categoryvarchar
mrrdecimal
arrdecimal
mrr_deltadecimal
seatsinteger
is_activeboolean

fct_usage_events

Grain: one row per product usage event

ColumnTypeKeys
usage_keybigintPK
date_keybigint
account_keybigint
user_keybigint
feature_keybigint
event_typevarchar
event_countinteger
event_timestamptimestamp
session_idvarchar

fct_invoices

Grain: one row per invoice

ColumnTypeKeys
invoice_keybigintPK
date_keybigint
account_keybigint
plan_keybigint
invoice_numbervarchar
due_date_keybigint
subtotaldecimal
tax_amountdecimal
total_amountdecimal
amount_paiddecimal
invoice_statusvarchar

fct_payments

Grain: one row per payment

ColumnTypeKeys
payment_keybigintPK
date_keybigint
account_keybigint
invoice_numbervarchar
amountdecimal
payment_methodvarchar
payment_statusvarchar

fct_support_tickets

Grain: one row per support ticket

ColumnTypeKeys
ticket_keybigintPK
created_date_keybigint
resolved_date_keybigint
account_keybigint
user_keybigint
agent_keybigint
ticket_numbervarchar
priorityvarchar
categoryvarchar
ticket_statusvarchar
csat_scoresmallint
first_response_minutesinteger
resolution_minutesinteger

Dimension tables (7)

dim_date

Grain: one row per calendar day

ColumnTypeKeys
date_keybigintPK
full_datedateBK
day_of_weeksmallint
month_numbersmallint
month_namevarchar
quartersmallint
yearsmallint
is_month_endboolean
fiscal_periodvarchar

dim_account

Grain: one row per account per SCD2 version

Type-2 SCD: plan tier and health score change over the lifecycle.

SCD type 2

ColumnTypeKeys
account_keybigintPK
account_idvarcharBK
account_namevarchar
industryvarchar
employee_bandvarchar
countryvarchar
regionvarchar
plan_tiervarchar
billing_currencyvarchar
csm_namevarcharPII
acquisition_channelvarchar
signup_datedate
health_scoresmallint
is_activeboolean

dim_user

Grain: one row per user per SCD2 version

SCD type 2

ColumnTypeKeys
user_keybigintPK
user_idvarcharBK
account_keybigint
emailvarcharPII
full_namevarcharPII
rolevarchar
seat_typevarchar
is_adminboolean
signup_datedate
last_login_datedate
is_activeboolean

dim_plan

Grain: one row per pricing plan

ColumnTypeKeys
plan_keybigintPK
plan_idvarcharBK
plan_namevarchar
plan_familyvarchar
billing_periodvarchar
list_pricedecimal
is_seat_basedboolean
feature_tiervarchar

dim_feature

Grain: one row per product feature

ColumnTypeKeys
feature_keybigintPK
feature_codevarcharBK
feature_namevarchar
modulevarchar
is_premiumboolean

dim_support_agent

Grain: one row per support agent

ColumnTypeKeys
agent_keybigintPK
agent_idvarcharBK
agent_namevarcharPII
teamvarchar
tiervarchar

dim_campaign

Grain: one row per marketing campaign

ColumnTypeKeys
campaign_keybigintPK
campaign_idvarcharBK
campaign_namevarchar
channelvarchar
start_datedate
end_datedate

Lookup tables (1)

dim_subscription_status

Grain: one row per status

ColumnTypeKeys
status_keybigintPK
status_codevarcharBK
status_namevarchar
is_payingboolean

Relationships

Each relationship is a foreign key on the first table referencing the second.

  • dim_user.account_key → dim_account (many-to-one)
  • fct_subscription.account_key → dim_account (many-to-one)
  • fct_subscription.plan_key → dim_plan (many-to-one)
  • fct_subscription.status_key → dim_subscription_status (many-to-one)
  • fct_subscription.start_date_key → dim_date (many-to-one)
  • fct_mrr_snapshot.date_key → dim_date (many-to-one)
  • fct_mrr_snapshot.account_key → dim_account (many-to-one)
  • fct_mrr_snapshot.plan_key → dim_plan (many-to-one)
  • fct_usage_events.date_key → dim_date (many-to-one)
  • fct_usage_events.account_key → dim_account (many-to-one)
  • fct_usage_events.user_key → dim_user (many-to-one)
  • fct_usage_events.feature_key → dim_feature (many-to-one)
  • fct_invoices.date_key → dim_date (many-to-one)
  • fct_invoices.account_key → dim_account (many-to-one)
  • fct_invoices.plan_key → dim_plan (many-to-one)
  • fct_payments.date_key → dim_date (many-to-one)
  • fct_payments.account_key → dim_account (many-to-one)
  • fct_support_tickets.created_date_key → dim_date (many-to-one)
  • fct_support_tickets.account_key → dim_account (many-to-one)
  • fct_support_tickets.user_key → dim_user (many-to-one)
  • fct_support_tickets.agent_key → dim_support_agent (many-to-one)

Related templates

All templates →
Start for $1

From requirements to AI-ready context, in one platform.

Describe your business in a conversation, start from a template or connect your own database. Your first model is ready in minutes.

Get startedBook a demo

Plans from $1/month · cancel any time