# CloudRevenue — Schema

> Synthetic cloud subscription revenue dataset. Three tables joined on `tenant_id` and `product_id`. 3 years of monthly grain ending 2026-05.

## Tables

### `products.csv` (8 rows)

| Column | Type | Notes |
| --- | --- | --- |
| `product_id` | string | Primary key. Format `P-XXXX`. |
| `product_name` | string | Display name of the product family. |
| `segment` | string | One of `Data`, `Infrastructure`, `Security`, `Operations`, `Productivity`. |
| `list_price_per_user_month_usd` | decimal | Reference list price; actual revenue applies size-band discount. |
| `growth_band` | string | One of `high`, `stable`, `declining`. Drives the per-month trend in the revenue table. |

### `tenants.csv` (247 rows)

| Column | Type | Notes |
| --- | --- | --- |
| `tenant_id` | string | Primary key. Format `T00000`. |
| `tenant_name` | string | Synthetic name, format `Tenant N`. |
| `size_band` | string | One of `SMB`, `Mid-Market`, `Enterprise`, `Strategic`. |
| `region` | string | **Known imperfection**: NA tenants are sometimes stored as `NA`, sometimes as `North America` (~12% of NA tenants). Chapter exercises can use this for naming-inconsistency cleanup. |
| `vertical` | string | One of 8 industry verticals. |
| `seats` | integer | Number of seats on the tenant's master agreement. Drives MAU baseline in revenue. |
| `first_contract_month` | date (ISO) | Earliest month the tenant has revenue. |
| `contract_size_tier` | string | One of `monthly`, `annual`, `multi-year`. |
| `churn_flag` | boolean | `true` for 12 mid-window churners. |
| `churn_month` | date (ISO) | Last month with revenue, if churned. Empty otherwise. |

### `revenue.csv` (~21,400 rows)

| Column | Type | Notes |
| --- | --- | --- |
| `month` | date (ISO) | First day of the month (e.g., `2025-03-01`). |
| `tenant_id` | string | Foreign key → `tenants.tenant_id`. |
| `product_id` | string | Foreign key → `products.product_id`. |
| `mau` | integer or NULL | Monthly active users. **Known imperfection**: ~2% null (telemetry outage). |
| `revenue_usd` | integer or NULL | Computed: `mau × list_price × discount_factor`. **Known imperfection**: last 2 months have ~30% nulls (billing close not complete). |
| `discount_factor` | decimal | The size-band discount applied (SMB=1.00, Mid-Market=0.92, Enterprise=0.82, Strategic=0.70). |

## Suggested chapter exercises

- **Chapter 3 (story)**: Build the headline narrative — which product families are driving Q4 portfolio decisions? Pair with the [CloudRevenue starter BRD](../../appendix-e/cloudrevenue-starter.md).
- **Chapter 4 (chart selection)**: Tenant-level concentration: which 10 tenants drive what % of revenue per product? Compare bar / treemap / Pareto encodings.
- **Chapter 5 (focus and decluttering)**: Strip the busy default dashboard down to a single 5-visual answer to "where should Q4 investment cuts land?"
- **Chapter 9 (Copilot report generation)**: Direct Copilot to build the portfolio review report; observe how the CSAR loop handles the region-naming inconsistency.
- **Chapter 10 (AI visuals)**: Key Influencers — what predicts revenue growth across product × tenant?
- **Chapter 13 (when AI misleads)**: Watch what Copilot does with the ~30% null revenue in the last 2 months. Does it surface the in-flight state, or compute averages as if the data were complete?

## Reproducibility

Generated by `scripts/datasets/generate-cloudrevenue.js` using a seeded PRNG. Rerunning the script produces byte-identical output. Source seed: `0xC10D5EED`.
