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. Because Metabase reads from SQL databases, the reliable way to connect them is a small pipeline: sync Zuora into a database or warehouse on a schedule, then point Metabase at it. This guide walks through that path end to end — including a free option with no paid connector.
How do you connect Zuora to Metabase?
Metabase connects to SQL databases and warehouses — not to SaaS APIs directly, and there's no native Zuora connector. So connecting Zuora to Metabase means one thing: run a small pipeline that copies Zuora data into a database on a schedule, then connect Metabase to that database. Once the data lands, the models, metrics, and SQL later in this guide all work.
The good news: this doesn't require a paid tool. Use a managed connector if you want zero maintenance, or a free, code-based sync you host yourself — both are covered in Build the pipeline below, and in more depth in our guide to building a data pipeline.
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 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.
Can you generate a Zuora dashboard with AI?
Yes — and once Zuora data is synced into a database, this is the fastest way to a strong first draft. First give an AI assistant a way to read your Metabase schema and create questions and dashboards, then paste the prompt below. It builds the dashboard from your database tables and tells the agent to skip metrics the schema can't support instead of faking them.
Two ways to let an assistant query and build in Metabase
Both connect to a Metabase instance that's already pointed at your synced database — the pipeline above moves the data; these just let the assistant read and write Metabase. Pick whichever fits your setup:
Metabase MCP
- Best for
- Chat clients (Claude, Cursor, Codex)
- Enable
- Admin → AI → MCP
- Endpoint
https://<your-metabase>/api/metabase-mcp- Auth
- OAuth handled by Metabase
Metabase CLI
- Best for
- Terminal agents, scripts, and CI
- Install
npm install -g @metabase/cli- Auth
- Browser OAuth (v62+) or an API key
- Docs
- @metabase/cli
Set up the Metabase MCP server
Enable it under Admin → AI → MCP, then point your client at the endpoint:
# Metabase built-in MCP (replace with your instance URL)
claude mcp add --transport http metabase https://your-metabase.example.com/api/metabase-mcp{
"mcpServers": {
"metabase": {
"command": "npx",
"args": ["-y", "mcp-remote", "https://your-metabase.example.com/api/metabase-mcp"]
}
}
}Clients with native remote support can use a "url" field instead of the mcp-remote bridge. Confirm the current endpoint in the Metabase MCP docs.
Set up the Metabase CLI
Install it globally, then authenticate once (the binary is mb):
# Install the CLI (the binary is `mb`)
npm install -g @metabase/cli
# Authenticate once — opens your browser on Metabase v62+, or use an API key
mb auth login --url https://your-metabase.example.com
mb auth statusOn Metabase v62+ mb auth login opens your browser; older servers fall back to an API key. A terminal-based assistant can then inspect your schema (mb db schemas, mb table get --include fields) and create content (mb card create, mb dashboard create) against the synced tables.
Prompt: build the Zuora Revenue Overview dashboard
With MCP or the CLI connected, paste this into your assistant to generate the dashboard:
Create a polished Metabase dashboard for Zuora subscription and revenue
analytics using the available Zuora tables in this database.
Goal: Help finance and RevOps leaders understand recurring revenue (MRR/ARR),
churn, billings, accounts receivable, and revenue recognition from Zuora data.
First, inspect the schema and identify the available Zuora tables. Do not assume
exact table names. Map the raw data into these analytical concepts where
possible: Accounts, Subscriptions, Rate plans, Rate plan charges, Products,
Invoices, Invoice items, Payments, and (if present) Revenue schedules.
Important:
- Build the dashboard from durable database/warehouse tables (Data Query,
AQuA/Data Source exports, or a managed connector).
- 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.
- Do not claim Metabase connects natively to Zuora unless that is explicitly
true in this environment.
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.
Before finalizing, create or recommend reusable Metabase 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 schema. Reconcile totals against
Zuora. Keep it practical, dense, and executive-readable. Avoid vanity metrics.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);