How to build Zuora revenue dashboards in Metabase
Zuora is an enterprise subscription-management and billing platform — accounts, rate plans, invoices, payments, and revenue recognition. Metabase is where you turn that into shared dashboards for MRR, churn, billings, and recognized revenue. This guide covers two complementary paths: a lightweight MCP + CLI route that pulls live data with the Zuora MCP server and loads a CSV into Metabase with the Metabase CLI for quick analysis, and a durable pipeline route that syncs Zuora into a database so you can build MRR, churn, and revenue-recognition dashboards anyone can read.
How do you connect Zuora to Metabase?
Most teams combine both routes: use the Zuora MCP server and Metabase CLI route to pull live data and stand up a quick analysis, and the pipeline route for the revenue dashboards finance depends on.
Live data in, quick analysis out
Pair Zuora's official MCP server (to look up live accounts, subscriptions, and invoices) with the Metabase CLI, whose upload command loads a CSV into Metabase as a ready-to-query table and model.
- Quick lookups like "which subscriptions renew next month?"
- Loading a Zuora CSV export into Metabase in seconds
- Spot-checks and one-off analyses without a warehouse
- Great for exploration, not governed revenue reporting
- Setup is tenant-specific and behind Zuora auth — use a read-only token
- CSV uploads are snapshots — refresh or move to the pipeline for history
Durable dashboards with history
Sync Zuora via Data Query, AQuA/Data Source exports, or a managed connector into a database, then point Metabase at it.
- MRR/ARR, churn, and billings dashboards finance relies on
- Cohort, retention, and revenue-recognition analysis
- Joining billing data with CRM, usage, and support data
- Requires a destination database and a sync to maintain
- Zuora's model is rich (rate plan charges) — modeling takes care
- Reconcile against Zuora before anyone trusts the numbers
What can you analyze from Zuora data in Metabase?
- MRR and ARR — recurring revenue now and its monthly movement
- Churn and retention — logo and revenue churn, gross and net retention
- Billings and AR — invoiced revenue, accounts receivable, DSO, and aging
- Revenue recognition — recognized vs. deferred revenue over time
- Bookings — new vs. renewal, TCV/ACV by product
- Failed payments and dunning — involuntary churn and recovery
Which Zuora dashboards should you build in Metabase?
MRR & ARR
Recurring revenue and its monthly movement.
- MRR and ARR right now (number + trend)
- MRR movement: new, expansion, contraction, churn (waterfall)
- ARR by product and rate plan (bar)
- New vs. renewal bookings (bar)
Churn & retention
Where recurring revenue leaks and how well you keep it.
- Gross and net revenue retention (line)
- Logo vs. revenue churn (dual line)
- Cancellations and downgrades by month (bar)
- Renewal rate by cohort (heatmap)
Billings & AR
Invoiced amounts and how fast they're collected.
- Invoiced revenue (billings) by month (bar)
- Accounts receivable and DSO (number + line)
- AR aging buckets (table)
- Failed payments and dunning recovery (line)
Revenue recognition
Recognized vs. deferred revenue over time.
- Recognized revenue by month (line)
- Deferred revenue balance (line)
- Revenue by recognition rule / product (bar)
- Billings vs. recognized (dual line)
How do you use the Zuora MCP server with the Metabase CLI?
Pair Zuora's MCP server with the Metabase CLI for fast, hands-on analysis. Zuora's remote MCP server looks up live accounts, subscriptions, and invoices; the Metabase CLI's upload command loads a CSV into Metabase and creates a ready-to-query table and model. For analysis, use a read-only OAuth token.
Example workflow
- Ask the Zuora MCP which subscriptions renew next month, or which invoices are past due over 60 days.
- Export the accounts, subscriptions, and invoices you want to keep as CSVs.
- Run
mb upload csvto load them into Metabase as tables and models, then build questions and dashboards on top.
Be honest about the limits
- The Zuora MCP is great for live lookups — not for scheduled or audited revenue reporting.
- A CSV upload is a point-in-time snapshot; MRR movement and recognition still need a warehouse sync, or refresh with
mb upload replace. - Zuora MCP setup is tenant-specific and behind Zuora auth.
mb upload csvneeds an uploads database configured under Admin → Settings → Uploads.
How do you set up the Zuora MCP server and the Metabase CLI?
Zuora MCPofficial
- Endpoint
- Tenant-specific (from Zuora Remote MCP setup)
- Transport
- Remote (Zuora-hosted)
- Auth
- Enable Zuora AI + OAuth client → bearer token
- Data center
- US / EU base URLs differ
Metabase CLIofficial
- Install
npm install -g @metabase/cli- Auth
mb auth login(browser OAuth on v62+, or an API key)- Load data
mb upload csv --file data.csv- Requires
- An uploads database (Admin → Settings → Uploads)
{
"mcpServers": {
"zuora": {
"url": "https://<your-zuora-mcp-endpoint>",
"headers": {
"Authorization": "Bearer <ZUORA_OAUTH_TOKEN>"
}
}
}
}# Install the Metabase CLI
npm install -g @metabase/cli
# Log in (opens your browser; requires Metabase v62+)
mb auth login --url https://your-metabase.example.com
# Load a Zuora CSV export — creates a table AND a model
mb upload csv --file zuora-subscriptions.csv --collection root
# Refresh that same table later from a new export
mb upload replace <table-id> --file zuora-subscriptions.csvThe Metabase CLI stores its credentials securely after mb auth login.
Can you generate a Zuora dashboard with AI?
Yes. Use the prompt below with any assistant that can run the Zuora MCP server and the Metabase CLI. It works end to end: if Zuora tables already exist in Metabase it analyzes those; otherwise it pulls the data over the Zuora MCP, loads it with mb upload csv, then builds the dashboard — modeling MRR from rate plan charges and skipping cards it has no data for.
Create a polished Metabase dashboard for Zuora subscription and revenue analytics.
Work end to end: get the data into Metabase if it isn't there yet, then build.
Goal: Help finance and RevOps leaders understand recurring revenue (MRR/ARR),
churn, billings, accounts receivable, and revenue recognition from Zuora data.
Step 1 — Find or load the data:
- First, check what already exists in Metabase (search for Zuora tables and
models). If durable Zuora data is already present — synced from a warehouse or
uploaded earlier — use it and skip to Step 2.
- If nothing is there, pull it with the Zuora MCP server using a read-only OAuth
token: accounts, subscriptions, rate plans, rate plan charges, products,
invoices, invoice items, payments, and (if present) revenue schedules. Write each
result to a CSV, then load it with the Metabase CLI — run "mb upload csv --file
<export>.csv" so each upload creates a table and a ready-to-query model. Use
"mb upload replace <table-id> --file <export>.csv" to refresh an existing table
instead of creating duplicates.
Step 2 — Inspect before querying:
Do not assume exact table names. Map the available raw tables into these
analytical concepts where possible: Accounts, Subscriptions, Rate plans, Rate
plan charges, Products, Invoices, Invoice items, Payments, and (if present)
Revenue schedules. Inspect the actual tables and column names first.
Important:
- Build on whatever data is present; don't claim Metabase connects natively to
Zuora — it reads a database or CLI-uploaded tables.
- Compute MRR from active rate plan charges, normalizing every charge to a
monthly amount (annual / 12, quarterly / 3, etc.).
- Separate one-time and usage charges from recurring charges so they don't
inflate MRR.
- For revenue recognition, use recognized/deferred revenue schedules, not
billings.
- Report in a single reporting currency; Zuora is multi-currency, so convert or
split by currency.
- Only build a card if its underlying column/metric exists in the data.
- A single CSV is a point-in-time snapshot: MRR movement and recognition need
history, so build trend cards only if a warehouse sync or multiple uploads
provide it.
Dashboard title: Zuora Revenue Overview
Sections:
1. Executive summary (KPI cards): MRR; ARR; Net new MRR; Gross revenue churn %;
Net revenue retention; Accounts receivable.
2. MRR & ARR: MRR movement by month; ARR by product/rate plan; New vs. renewal
bookings.
3. Churn & retention: Logo vs. revenue churn; Gross vs. net retention; Renewal
rate by cohort.
4. Billings & AR: Invoiced revenue; AR aging; Failed payments and dunning.
5. Revenue recognition: Recognized vs. deferred revenue; Billings vs.
recognized.
Filters: Product, Rate plan, Currency, Account segment, Date range.
Reuse the models Metabase auto-created from uploaded CSVs, or (for a warehouse)
create reusable models: modeled_zuora_subscriptions, modeled_zuora_charges,
modeled_zuora_invoices, and modeled_zuora_mrr (a monthly per-charge MRR model).
Output: Build the dashboard if you have permission; otherwise provide the exact
questions, SQL, model definitions, and layout. Include caveats for any metric
that cannot be calculated from the available data. Reconcile totals against
Zuora. Keep it practical, dense, and executive-readable. Avoid vanity metrics.How do you build the Zuora → Metabase pipeline?
For dashboards that need history and reliability, land Zuora data in a database first, then connect Metabase to that database.
Connector options
- dlt (free, code) — wrap Zuora's Data Query or REST API in a small Python pipeline for incremental, no-vendor loads. The lightest path to a maintainable sync.
- Data Query (first-party) — run SQL-like queries against your Zuora tenant and load results into your warehouse.
- AQuA / Data Source exports (bulk) — export large objects (subscriptions, invoices, charges) on a schedule.
- Airbyte — has a Zuora source connector; free if you self-host the open-source version, paid on Airbyte Cloud.
- Fivetran (paid, managed) — a maintained Zuora connector with incremental syncs and zero maintenance.
Notes
- Land raw tables first, then build clean models on top.
- MRR lives in rate plan charges, not subscriptions — normalize each charge to a monthly amount.
- Separate recurring from one-time and usage charges.
- Use revenue schedules (not billings) for recognized/deferred revenue.
How should you model Zuora data in Metabase?
Core tables
| Concept | Grain | Key columns |
|---|---|---|
account | one row per account | id, name, currency, status |
subscription | one row per subscription version | id, account_id, subscription_start_date, cancelled_date, status, version |
rate_plan_charge | one row per charge | id, subscription_id, product_id, charge_type, mrr, tcv, billing_period |
invoice | one row per invoice | id, account_id, amount, balance, status, invoice_date, due_date |
payment | one row per payment | id, account_id, amount, status, effective_date |
Modeling advice
- Build a
modeled_zuora_mrrtable from active recurring rate plan charges — Zuora even stores a per-chargemrr, but normalize consistently. - Handle subscription versions/amendments so you count each subscription once.
- Separate recurring, one-time, and usage charge types.
- Use revenue schedules for recognized vs. deferred, not invoice amounts.
- Reconcile modeled MRR and AR against Zuora before trusting the numbers.
Which Zuora metrics should you track in Metabase?
| Metric | Definition | Notes |
|---|---|---|
| MRR / ARR | Active recurring charges, normalized monthly. | From rate plan charges, not subscriptions. |
| Net new MRR | New + expansion − contraction − churn. | Best as a monthly waterfall. |
| Revenue churn rate | Churned MRR ÷ MRR at period start. | Track separately from logo churn. |
| Net revenue retention | (Start + expansion − contraction − churn) ÷ start. | Over 100% = expansion beats churn. |
| Recognized revenue | Revenue earned per recognition rules. | From revenue schedules, not billings. |
| DSO | Avg days to collect an invoice. | Compute from open invoices. |
What SQL powers Zuora dashboards in Metabase?
These assume the modeled tables above (PostgreSQL dialect). Adjust identifiers to match your export schema.
Sum a monthly MRR model built from active rate plan charges.
-- Requires a monthly MRR model built from active Zuora rate plan charges
SELECT
ROUND(SUM(mrr), 2) AS mrr,
ROUND(SUM(mrr) * 12, 2) AS arr,
COUNT(DISTINCT subscription_id) AS active_subscriptions
FROM modeled_zuora_mrr
WHERE month = date_trunc('month', CURRENT_DATE);Cancellations against subscriptions active at each month's start.
-- Cancellations against subscriptions active at each month's start
WITH months AS (
SELECT generate_series(
date_trunc('month', CURRENT_DATE - INTERVAL '11 months'),
date_trunc('month', CURRENT_DATE),
INTERVAL '1 month'
) AS month
)
SELECT
m.month,
COUNT(*) FILTER (
WHERE date_trunc('month', s.cancelled_date) = m.month
) AS churned_subscriptions,
COUNT(*) FILTER (
WHERE s.subscription_start_date <= m.month
AND (s.cancelled_date IS NULL OR s.cancelled_date > m.month)
) AS active_at_month_start
FROM months m
CROSS JOIN subscriptions s
GROUP BY m.month
ORDER BY m.month;Open invoice balances bucketed by days past due.
-- AR aging from open invoices
SELECT
CASE
WHEN CURRENT_DATE - due_date <= 0 THEN 'current'
WHEN CURRENT_DATE - due_date <= 30 THEN '1-30'
WHEN CURRENT_DATE - due_date <= 60 THEN '31-60'
ELSE '60+'
END AS aging_bucket,
COUNT(*) AS invoices,
ROUND(SUM(balance), 2) AS open_balance
FROM invoices
WHERE status = 'Posted' AND balance > 0
GROUP BY 1
ORDER BY MIN(CURRENT_DATE - due_date);