Medusa × Metabase

How to build Medusa dashboards in Metabase

Medusa is the open-source, headless commerce platform built on Node.js, and it keeps every order, product, and customer in a PostgreSQL database you control. Metabase is where you turn that store data into shared, trustworthy dashboards. This guide covers two complementary paths: a lightweight MCP + CLI route that pulls live data with the Medusa MCP server and loads a CSV into Metabase with the Metabase CLI for quick analysis, and a durable direct-database route that connects Metabase straight to Medusa's Postgres so you can build dashboards anyone can read.

Key advantage: because Medusa data lives in your own Postgres, the "sync step" that hosted platforms need is often optional. Connect a read replica and query it directly.

How do you connect Medusa to Metabase?

Most teams combine both routes: use the Medusa MCP server and Metabase CLI route to pull live data and stand up a quick analysis, and the direct-database route for the dashboards people depend on.

1 · MCP + CLI route (AI-assisted)

Live data in, quick analysis out

Pair Medusa's MCP server (to read live store data) with the Metabase CLI, whose upload command loads a CSV into Metabase as a ready-to-query table and model.

Best for
  • Quick lookups like "how many orders did we ship this week?"
  • Loading a Medusa CSV export into Metabase in seconds
  • Spot-checks and one-off analyses without wiring up the database
Trade-offs
  • Great for exploration, not governed reporting
  • Use read-only mode on the Medusa MCP to avoid accidental writes
  • CSV uploads are snapshots — connect the database directly for live, ongoing analysis
2 · Direct database (fastest)

Point Metabase at your Postgres

Medusa is a self-hosted, open-source commerce platform that stores everything in PostgreSQL. Metabase connects to Postgres natively, so you can query orders and products directly — no ETL required.

Best for
  • Self-hosted stores where you control the database
  • Getting to a first dashboard in minutes
  • Live operational reporting on a read replica
Trade-offs
  • Query a read replica, never the live production writer
  • Medusa v2's module tables differ from v1 — check your version
  • Money is stored in minor units on some fields — normalize it

What can you analyze from Medusa data in Metabase?

  • Sales — net revenue, orders, and AOV over time
  • Repeat purchase — how many buyers come back, and how fast
  • Product performance — top sellers, units, and return rate
  • Regions & channels — revenue split across markets
  • Fulfillment & payments — order status and capture rates
  • Customer cohorts — revenue by acquisition month

Which Medusa dashboards should you build in Metabase?

For: Store owners

Store overview

The daily pulse of sales and demand.

  • Net revenue vs. prior period (number + trend)
  • Orders per day (line)
  • Average order value (number + trend)
  • New vs. returning customer revenue (bar)
For: Merchandising

Product performance

What's selling across the catalog.

  • Top products by net revenue (bar)
  • Units sold by variant (table)
  • Return rate by product (bar)
  • Revenue by region / sales channel (bar)
For: Growth / retention

Customers & repeat purchase

Are buyers coming back?

  • Repeat-purchase rate by cohort (line)
  • Orders per customer distribution (bar)
  • Time between first and second order (histogram)
  • Revenue by acquisition month (cohort table)
For: Ops & finance

Fulfillment & payments

From cart to captured.

  • Order status funnel (pending → completed) (bar)
  • Payment capture vs. authorization (bar)
  • Refunds by week (line)
  • Cart-to-order conversion (number)

How do you connect the Medusa database directly?

In Metabase, add your Medusa database under Admin → Databases → Add database → PostgreSQL, using a read-only user against a replica. A few things to know:

  • Version matters — Medusa v2 organizes data into module tables like order, order_line_item, and product_variant; v1's layout differs. Confirm which you run.
  • Money units — some totals are stored in minor units (e.g. cents). Normalize by dividing where needed.
  • Reserved wordsorder is a SQL keyword; quote it ("order") in queries.
Never query the production writer. Point Metabase at a read replica (or a nightly warehouse copy) so analytical queries can't slow down the storefront.

How do you use the Medusa MCP server with the Metabase CLI?

Pair the Medusa MCP server with the Metabase CLI for fast, hands-on analysis. Medusa hosts an official Streamable-HTTP MCP server for its docs and developer workflows — useful for understanding the schema and drafting queries against live store data; the Metabase CLI's upload command loads a CSV into Metabase and creates a ready-to-query table and model. For analysis, connect Medusa in read-only mode.

Example workflow

  • Ask the Medusa MCP how orders and line items relate, and which rows to pull this week.
  • Export the orders or products you want to keep as a CSV.
  • Run mb upload csv to load it into Metabase as a table and model, then build questions and dashboards on top.

Be honest about the limits

  • The Medusa MCP is docs/dev focused and great for live lookups — not for scheduled or audited reporting.
  • A CSV upload is a point-in-time snapshot; refresh it with mb upload replace or connect the database directly for real history.
  • Use Medusa's read-only option so analysis can't trigger writes.
  • mb upload csv needs an uploads database configured under Admin → Settings → Uploads.

How do you set up the Medusa MCP server and the Metabase CLI?

Medusa MCPofficial

Endpoint
https://docs.medusajs.com/mcp
Transport
Streamable HTTP
Auth
Authorization: Bearer <token>
Scope
Docs and developer workflows

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)
Cursor~/.cursor/mcp.json or .cursor/mcp.json
{
  "mcpServers": {
    "medusa": {
      "command": "npx",
      "args": [
        "-y",
        "mcp-remote",
        "https://docs.medusajs.com/mcp",
        "--header",
        "Authorization: Bearer YOUR_TOKEN"
      ]
    }
  }
}
TerminalLoad a Medusa CSV with the Metabase CLI
# 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 Medusa CSV export — creates a table AND a model
mb upload csv --file medusa-orders.csv --collection root

# Refresh that same table later from a new export
mb upload replace <table-id> --file medusa-orders.csv

Cursor's OAuth flow can be flaky, so the Medusa docs recommend the URL plus a Bearer token. Replace YOUR_TOKEN with your token. The Metabase CLI stores its credentials securely after mb auth login, and mb upload csv needs an uploads database enabled first.

Verify before shipping: confirm an uploads database is enabled under Admin → Settings → Uploads (Metabase docs) and the current Medusa MCP setup in the Medusa docs.

Can you generate a Medusa dashboard with AI?

Yes. Use the prompt below with any assistant that can run the Medusa MCP server and the Metabase CLI. It works end to end: if Medusa data already lives in Metabase — the connected Postgres database or CLI-uploaded tables — it analyzes that; otherwise it pulls the data over the Medusa MCP, loads it with mb upload csv, then builds the dashboard — detecting the Medusa version, normalizing money units, and skipping cards it has no data for.

Prompt for creating a Medusa Store Overview dashboard
Create a polished Metabase dashboard for Medusa ecommerce analytics.
Work end to end: get the data into Metabase if it isn't there yet, then build.

Goal: Help store operators understand sales, average order value, repeat purchase,
product performance, and fulfillment from Medusa data.

Step 1 — Find or load the data:
- First, check what already exists in Metabase. If the Medusa Postgres database is
  already connected — or Medusa tables/models were uploaded earlier — use that data
  and skip to Step 2.
- If nothing is there, pull it with the Medusa MCP server in read-only mode: orders,
  line items, products, and customers. 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:
Medusa CSV exports are usually flat and pre-aggregated (one row per order or product,
with columns already summarized). The Medusa database is raw: identify the Medusa
version and table layout first. Medusa v2 uses module tables such as "order",
"order_line_item", "product", "product_variant", "customer", and "cart"; v1 differs.
Note that "order" is a reserved word — quote it. Some money fields are stored in
minor units (e.g. cents) — normalize them. Inspect the actual tables and column names
first; do not assume exact names.

Important:
- Build on whatever data is present; don't claim Metabase connects natively to
  Medusa — it reads the connected SQL database or CLI-uploaded tables.
- Query a read replica, not the production writer.
- Report NET revenue: subtract refunds and discounts; state the definition.
- Count only completed/captured orders per your definition of paid.
- Use order-level grain for AOV.
- Define a "repeat customer" once (2+ paid orders) and reuse it everywhere.
- Only build a card if its underlying column/metric exists in the data.
- A single CSV is a point-in-time snapshot: connect the database directly or upload
  multiple periods before building trend cards.

Dashboard title: Medusa Store Overview

Sections:
1. Executive summary (KPI cards): Net revenue last 30 days; Orders; AOV; Repeat-
   purchase rate; Refund rate.
2. Sales & demand: Net revenue by day; Orders by day; AOV trend; New vs returning
   revenue.
3. Product performance: Top products by net revenue; Units by variant; Return rate.
4. Customers & retention: Repeat-purchase rate by cohort; Orders per customer;
   Revenue by acquisition month.
5. Fulfillment & payments: Order status funnel; Payment capture; Refunds by week.

Filters: Date range, Region, Sales channel, Product, Customer type.

Reuse the models Metabase auto-created from uploaded CSVs, or (for the database)
create reusable models: modeled_medusa_orders, modeled_medusa_line_items,
modeled_medusa_products, and modeled_medusa_customers.

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. Keep it practical, dense,
and executive-readable. Avoid vanity metrics.

How should you model Medusa data in Metabase?

Core tables (Medusa v2)

TableGrainKey columns
orderone row per orderid, customer_id, status, total, currency_code, created_at
order_line_itemone row per lineorder_id, variant_id, quantity, unit_price
productone row per productid, title, status
product_variantone row per variantid, product_id, sku
customerone row per customerid, email, created_at

Modeling advice

  • Quote the order table name — it's a SQL reserved word.
  • Normalize money from minor units and label the currency.
  • Compute AOV at the order grain; define net revenue once.
  • Join line items through product_variant to product for product-level analysis.

Which Medusa metrics should you track in Metabase?

MetricDefinitionNotes
Net revenueGross − discounts − refunds.Normalize money units first.
Average order value (AOV)Net revenue ÷ orders.Order grain; segment by region.
Repeat-purchase rateCustomers with 2+ paid orders ÷ all.Fixed window; watch by cohort.
Return rateReturned value ÷ gross.Break out by product.
Cart-to-order conversionOrders ÷ carts created.Needs cart data; watch by channel.

What SQL powers Medusa dashboards in Metabase?

These assume a Medusa v2 PostgreSQL database. Money is divided by 100 to illustrate minor-unit normalization — adjust to your configuration.

Net revenue and orders per dayPostgreSQL

Completed-order totals over the last 30 days.

-- Medusa v2 module tables; money often in minor units
SELECT
  date_trunc('day', o.created_at)     AS day,
  COUNT(*)                            AS orders,
  SUM(o.total) / 100.0                AS net_revenue
FROM "order" o
WHERE o.status = 'completed'
  AND o.created_at >= CURRENT_DATE - INTERVAL '30 days'
GROUP BY 1
ORDER BY 1;
Average order value by weekPostgreSQL

AOV computed at the order grain, on completed orders.

SELECT
  date_trunc('week', o.created_at) AS week,
  COUNT(*)                         AS orders,
  ROUND((SUM(o.total) / 100.0) / NULLIF(COUNT(*), 0), 2) AS aov
FROM "order" o
WHERE o.status = 'completed'
GROUP BY 1
ORDER BY 1;
Top products by revenuePostgreSQL

Units and gross revenue by product over 90 days.

SELECT
  p.title                          AS product,
  SUM(li.quantity)                 AS units,
  SUM(li.quantity * li.unit_price) / 100.0 AS gross_revenue
FROM order_line_item li
JOIN "order" o          ON o.id = li.order_id
JOIN product_variant v  ON v.id = li.variant_id
JOIN product p          ON p.id = v.product_id
WHERE o.status = 'completed'
  AND o.created_at >= CURRENT_DATE - INTERVAL '90 days'
GROUP BY p.title
ORDER BY gross_revenue DESC
LIMIT 20;
Repeat-purchase ratePostgreSQL

Share of customers with two or more paid orders.

WITH customer_orders AS (
  SELECT customer_id, COUNT(*) AS paid_orders
  FROM "order"
  WHERE status = 'completed'
    AND customer_id IS NOT NULL
  GROUP BY customer_id
)
SELECT
  ROUND(100.0 * COUNT(*) FILTER (WHERE paid_orders >= 2)
    / NULLIF(COUNT(*), 0), 2) AS repeat_purchase_rate_pct
FROM customer_orders;

What are common mistakes when analyzing Medusa in Metabase?

Querying the live production database.→ Analytical queries can slow the storefront. Use a read replica or warehouse copy.
Forgetting money is in minor units.→ Totals stored in cents will overstate revenue 100× if not normalized.
Not quoting the reserved word order.→ Wrap it in double quotes so the query parses.
Assuming v1 and v2 share a schema.→ Medusa v2 reorganized data into module tables; confirm your version.
Averaging line-item prices for AOV.→ Compute AOV at the order grain, or multi-item baskets skew the number.

Related analytics

Related integrations

FAQ

Can Metabase connect directly to Medusa?
Yes — Medusa data lives in a PostgreSQL database, and Metabase connects to Postgres natively. Point it at a read replica (not the production writer) and you can query orders, products, and customers without any ETL.
Is the Medusa MCP server official?
Yes. Medusa hosts an official Streamable-HTTP MCP server at docs.medusajs.com/mcp for its docs and developer workflows. In Cursor, use the URL plus an Authorization Bearer token since the OAuth flow can be flaky.
How do I quickly load Medusa data without connecting the database?
Export a CSV from Medusa and run `mb upload csv --file data.csv` with the Metabase CLI. It creates a table and a model you can build questions on right away. You'll need an uploads database enabled under Admin → Settings → Uploads. Refresh later with `mb upload replace`, or connect the Postgres database directly when you need live, ongoing analysis.
How do I handle Medusa's money fields?
Some totals are stored in minor units (e.g. cents). Normalize them in your models by dividing, and always label the currency so multi-region revenue stays consistent.