How to build Recurly revenue dashboards in Metabase
Recurly runs your subscription management, billing, and dunning. Metabase is where you turn that billing activity into shared, trustworthy revenue dashboards. This guide covers two complementary paths: a lightweight MCP + CLI route that pulls live data with a Recurly MCP server and loads a CSV into Metabase with the Metabase CLI for quick analysis, and a durable pipeline route that syncs Recurly into a database so you can build MRR, churn, and retention dashboards anyone can read.
How do you connect Recurly to Metabase?
Most teams combine both routes: use the Recurly 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 a community Recurly 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 are in a dunning state?"
- Loading a Recurly CSV export into Metabase in seconds
- Spot-checks and one-off analyses without a warehouse
- Great for exploration, not governed revenue reporting
- Recurly's MCP is community-maintained — use a read-only key and vet the package
- CSV uploads are snapshots — refresh or move to the pipeline for history
Durable dashboards with history
Sync Recurly into a database or warehouse with a connector, Recurly's export files, or the v3 API, then point Metabase at it.
- MRR/ARR, churn, and retention dashboards finance relies on
- Cohort and trend analysis over quarters and years
- Joining billing data with product usage, support, or CRM data
- Requires a destination database and a sync to maintain
- You own the revenue definitions and refresh schedule
- Reconcile against Recurly's own analytics before trusting numbers
What can you analyze from Recurly data in Metabase?
- MRR and ARR — recurring revenue now and its monthly movement
- Churn and retention — customer and revenue churn, gross and net retention
- Expansion and contraction — plan changes, add-ons, and quantities
- Failed payments and dunning — declines, recovery, and involuntary churn
- Trials and conversion — trial-to-paid rate and time to convert
- LTV and ARPU — value per customer and per account
- Cohort revenue — how each signup cohort retains and grows
Which Recurly dashboards should you build in Metabase?
MRR & ARR
The core recurring-revenue picture, month over month.
- MRR and ARR right now (number + trend)
- MRR movement: new, expansion, contraction, churn (waterfall)
- Net new MRR per month (bar)
- ARR by plan and billing interval (bar)
Churn & retention
Where recurring revenue leaks and how well you keep it.
- Gross and net revenue retention by month (line)
- Customer vs. revenue churn rate (dual line)
- Churn by plan (bar)
- Trial-to-paid conversion rate (number)
Failed payments & dunning
Recover revenue lost to declines before it becomes churn.
- Failed transactions and $ at risk this month (number)
- Dunning recovery rate (line)
- Declines by reason (bar)
- Past-due subscriptions by age (table)
Cohort revenue
Does each signup cohort grow or decay over time?
- Revenue retention by signup-month cohort (heatmap)
- Cumulative LTV by cohort (line)
- ARPU by plan and cohort (table)
- Expansion revenue by cohort (bar)
How do you use the Recurly MCP server with the Metabase CLI?
Pair a Recurly MCP server with the Metabase CLI for fast, hands-on analysis. A community Recurly MCP server looks up live accounts, subscriptions, and invoices over the v3 API; the Metabase CLI's upload command loads a CSV into Metabase and creates a ready-to-query table and model. For analysis, scope the Recurly key to read-only.
Example workflow
- Ask the Recurly MCP which subscriptions are in a dunning/past-due state, or pull an account's invoices and transactions.
- Export the accounts, subscriptions, invoices, and transactions 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 Recurly 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 cohorts still need a warehouse sync, or refresh with
mb upload replace. - The Recurly MCP server is community-maintained and read-only — review the package and use a scoped key.
mb upload csvneeds an uploads database configured under Admin → Settings → Uploads.
How do you set up the Recurly MCP server and the Metabase CLI?
Recurly MCP community
- Package
recurly-mcp(npm)- Auth
RECURLY_API_KEY(private key)- Region
RECURLY_REGION:usoreu- Note
- Read-only; issues GET requests against the v3 API.
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": {
"recurly": {
"command": "npx",
"args": ["-y", "recurly-mcp"],
"env": {
"RECURLY_API_KEY": "YOUR_PRIVATE_API_KEY",
"RECURLY_REGION": "us"
}
}
}
}Use the eu region if your Recurly site is EU-hosted. Because this is a community server, review the package source and use a read-only key.
# 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 Recurly CSV export — creates a table AND a model
mb upload csv --file recurly-subscriptions.csv --collection root
# Refresh that same table later from a new export
mb upload replace <table-id> --file recurly-subscriptions.csvThe Metabase CLI stores its credentials securely after mb auth login.
Can you generate a Recurly dashboard with AI?
Yes. Use the prompt below with any assistant that can run the Recurly MCP server and the Metabase CLI. It works end to end: if Recurly tables already exist in Metabase it analyzes those; otherwise it pulls the data over the Recurly MCP, loads it with mb upload csv, then builds the dashboard — normalizing MRR and skipping cards it has no data for.
Create a polished Metabase dashboard for Recurly revenue analytics.
Work end to end: get the data into Metabase if it isn't there yet, then build.
Goal: Help founders and finance leaders understand recurring revenue, churn,
retention, failed payments, and cohort economics from Recurly data.
Step 1 — Find or load the data:
- First, check what already exists in Metabase (search for Recurly tables and
models). If durable Recurly 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 Recurly MCP server using a read-only
API key: accounts, subscriptions, plans, invoices, and transactions. 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, Subscription
add-ons, Plans, Invoices, Line items, Transactions, and Coupon redemptions.
Inspect the actual tables and column names first.
Important:
- Build on whatever data is present; don't claim Metabase connects natively to
Recurly — it reads a database or CLI-uploaded tables.
- Compute MRR from active subscriptions, normalizing every plan to a monthly
amount (divide annual by 12, etc.). Recurly v3 amounts are already in major
currency units (decimals), so do not divide by 100 unless your pipeline stored
minor units.
- Report revenue in a single reporting currency; if multiple currencies exist,
convert with a documented rate or caveat the mix.
- Separate voluntary churn from involuntary (failed-payment) churn.
- Exclude one-time charges and setup fees from MRR unless explicitly asked.
- 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 cohorts need history,
so build trend cards only if a warehouse sync or multiple uploads provide it.
Dashboard title: Recurly Revenue Overview
Sections:
1. Executive summary (KPI cards): MRR; ARR; Active subscriptions; Net new MRR this
month; Gross revenue churn %; Net revenue retention (only if MRR-movement data
can be derived).
2. MRR movement: New, expansion, contraction, and churned MRR by month.
3. Churn & retention: Customer vs. revenue churn by month; Gross vs. net retention;
Churn by plan; Trial-to-paid conversion.
4. Failed payments & dunning: Failed transactions and $ at risk; Dunning recovery
rate; Declines by reason; Past-due subscriptions by age.
5. Cohorts & LTV: Revenue retention by signup-month cohort; Cumulative LTV by
cohort; ARPU by plan.
Filters: Plan, Billing interval, Currency, Account state, Date range.
Reuse the models Metabase auto-created from uploaded CSVs, or (for a warehouse)
create reusable models: modeled_recurly_accounts, modeled_recurly_subscriptions,
modeled_recurly_invoices, modeled_recurly_transactions, and modeled_recurly_mrr
(a monthly per-subscription 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 Recurly's
analytics. Keep it practical, dense, and executive-readable. Avoid vanity metrics.How do you build the Recurly → Metabase pipeline?
For dashboards that need history and reliability, land Recurly data in a database first, then connect Metabase to that database.
Connector options
- dlt (free, code) — write a Python pipeline against the Recurly v3 API for full control.
- Recurly API (v3) (free, raw) — the source of truth; paginate resources and sync on a schedule.
- Recurly export files (first-party) — scheduled data exports you can load into your warehouse.
- Airbyte — has a Recurly source covering accounts, subscriptions, invoices, transactions, plans, and more. Free if you self-host the open-source version; paid on Airbyte Cloud.
Notes
- Land raw tables first, then build clean models on top.
- Recurly v3 API amounts are decimals in the major currency unit — don't divide by 100 unless your pipeline stored minor units.
- A subscription's
stateplusexpires_atdefines whether it's still billing; use both. - MRR is derived: build it from active subscriptions and their plans.
How should you model Recurly data in Metabase?
Core tables
| Table | Grain | Key columns |
|---|---|---|
accounts | one row per account | id, email, created_at, state |
subscriptions | one row per subscription | id, account_id, plan_id, unit_amount, quantity, state, activated_at, canceled_at, expires_at |
plans | one row per plan | id, name, interval_unit, interval_length, currency |
invoices | one row per invoice | id, account_id, subscription_ids, state, total, created_at |
transactions | one row per transaction | id, account_id, amount, type, status, status_message, created_at |
line_items | one row per line item | id, invoice_id, subscription_id, amount, type |
Modeling advice
- Build a
modeled_recurly_mrrtable: one row per subscription per month with a normalized monthly amount. - Normalize all plans to a monthly figure (annual ÷ 12, etc.) and to one reporting currency.
- Define subscription state once (active / canceled / expired / future) and combine with
expires_atto decide who is still billing. - Keep setup fees and one-time charges out of MRR.
- Reconcile modeled MRR against Recurly's analytics before trusting it.
Which Recurly metrics should you track in Metabase?
| Metric | Definition | Notes |
|---|---|---|
| MRR | Sum of active subscriptions' normalized monthly amount. | Recurring only; exclude setup and one-time fees. |
| Net new MRR | New + expansion − contraction − churned MRR. | Best shown as a monthly waterfall. |
| Revenue churn rate | Churned MRR ÷ MRR at period start. | Track separately from customer churn. |
| Net revenue retention | (Starting MRR + expansion − contraction − churn) ÷ starting MRR. | Over 100% means expansion beats churn. |
| Trial-to-paid conversion | Trials that activated a paid subscription ÷ trials started. | Watch time-to-convert too. |
| Failed-payment rate | Declined transactions ÷ attempted transactions. | The main driver of involuntary churn. |
| LTV | ARPU × average customer lifetime (1 ÷ churn rate). | Treat as a range, not a point. |
What SQL powers Recurly dashboards in Metabase?
These assume the modeled tables above (PostgreSQL dialect, v3 amounts in major currency units). Adjust identifiers to match your warehouse.
Normalize active subscriptions to a monthly amount and sum.
SELECT
ROUND(SUM(
CASE p.interval_unit
WHEN 'years' THEN s.unit_amount / 12.0 / NULLIF(p.interval_length, 0)
WHEN 'months' THEN s.unit_amount / NULLIF(p.interval_length, 0)
END * s.quantity
), 2) AS mrr_now
FROM subscriptions s
JOIN plans p ON p.id = s.plan_id
WHERE s.state IN ('active', 'canceled') -- canceled but not yet expired still bills
AND (s.expires_at IS NULL OR s.expires_at > CURRENT_DATE);Expirations 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.expires_at) = m.month
) AS churned_subscriptions,
COUNT(*) FILTER (
WHERE s.activated_at <= m.month
AND (s.expires_at IS NULL OR s.expires_at > m.month)
) AS active_at_month_start
FROM months m
CROSS JOIN subscriptions s
GROUP BY m.month
ORDER BY m.month;Declined transactions by week and reason — the dunning worklist.
SELECT
date_trunc('week', t.created_at) AS week,
COUNT(*) AS failed_transactions,
ROUND(SUM(t.amount), 2) AS dollars_at_risk,
t.status_message
FROM transactions t
WHERE t.status = 'declined'
AND t.created_at >= CURRENT_DATE - INTERVAL '90 days'
GROUP BY 1, t.status_message
ORDER BY 1, dollars_at_risk DESC;What are common mistakes when analyzing Recurly in Metabase?
expires_at; combine state with the expiry date.