Founder & Lead Engineer, RAITHub
Build customer-facing analytics yourself when you need a handful of fixed charts that look like the rest of your product. Embed a BI tool when customers want to filter, drill down and build their own reports. Either way, the tenant filter must be set on the server, never in the browser, and dashboards should read from rollup tables or a replica, not your live transactional tables.
If you would rather have analytics built into your product for you, see how RAITHub would build this below.
What is embedded analytics in a SaaS, and what do customers actually expect?
Embedded analytics means dashboards and reports about the customer's own data, shown inside your product: "invoices paid this month", "response time by agent", "bookings by location". It is different from your internal analytics, which is about your business across all customers.
Customer expectations fall into three levels, and the level decides the route far more than the charting library does.
| Level | What the customer gets | Typical route |
|---|---|---|
| 1. Fixed metrics | A few KPIs and charts on a home screen, with a date range picker | Build it: an API endpoint per metric and a charting library |
| 2. Interactive reports | Filters, drill-down, CSV export, scheduled email reports | Either; building gets expensive as the number of reports grows |
| 3. Self-service exploration | Customers build their own charts and dashboards from your data model | Embed a BI tool or a semantic layer; rebuilding a query builder is rarely worth it |
Most products start at level 1 and are pushed towards level 3 by larger customers. Ask your sales team which level is blocking deals before choosing a tool.
What does embedding a BI tool cost in 2026?
Pricing models vary: per user, per developer, per viewer, or by usage. Two published examples, checked on 7 October 2026:
- Metabase. The Metabase pricing page lists a free open-source edition, Starter at $100 a month with 5 users included, Pro at $575 a month with 10 users included and $12 per extra user per month, and Enterprise from $20,000 a year. Its embedding docs say guest authentication and public embeds work on all plans, including open source, while all SSO options for embedding require Pro or Enterprise.
- Cube. Cube Cloud pricing lists a free tier, Starter at $40 per developer a month and Premium at $80 per developer a month, with embedded dashboards on Premium and Enterprise, viewer seats at $20 per user a month, and hourly charges for dedicated deployments.
The units are the trap. A per-user price that is fine for 10 internal analysts can become your largest cost line when 2,000 customer users each count as a viewer. Model your own user numbers against each pricing page, and read what counts as a user for embedded use before you sign.
How do you keep one customer from seeing another customer's analytics?
Set the tenant on the server and sign it, so the browser cannot change it. This is the single most important rule, and the most common failure: a dashboard URL with ?tenant_id=42 that anyone can edit to 43.
With an embedded tool, your back end creates a short-lived signed token that names the dashboard and locks the tenant parameter; the browser only ever receives the token. The exact payload differs by vendor, so follow your tool's docs, but the shape is the same:
import { SignJWT } from 'jose'
const secret = new TextEncoder().encode(process.env.EMBED_SECRET!)
// Called by YOUR authenticated API route. tenantId comes from the session, never the request body.
export async function embedToken(session: { tenantId: string; userId: string }, dashboardId: number) {
return new SignJWT({
resource: { dashboard: dashboardId },
params: { tenant_id: session.tenantId }, // locked: the viewer cannot change it
})
.setProtectedHeader({ alg: 'HS256' })
.setIssuedAt()
.setExpirationTime('10m') // short-lived; refresh from your app
.sign(secret)
}
Then add a second, independent layer in the database, so a misconfigured dashboard still cannot cross tenants. Give the analytics tool its own read-only database role and enforce row-level security on every table it can read:
CREATE ROLE analytics_reader NOLOGIN;
GRANT SELECT ON tenant_daily_rollups TO analytics_reader;
ALTER TABLE tenant_daily_rollups ENABLE ROW LEVEL SECURITY;
CREATE POLICY tenant_only ON tenant_daily_rollups
FOR SELECT TO analytics_reader
USING (tenant_id = current_setting('app.tenant_id')::uuid);
Whether a given BI tool can set app.tenant_id per query depends on the tool and plan; if it cannot, rely on locked, signed parameters and test them hard. The patterns and the test cases are in the Postgres row-level security guide and users can see other tenants' data.
Should dashboards query your production database?
Not your live tables directly, once you have real data. Analytics queries scan many rows, and one customer's year-long report can slow down every other customer's checkout or save button. Use, in order of effort:
- A read replica for reporting traffic, so heavy reads do not compete with writes.
- Rollup tables written by a scheduled job or on each event: one row per tenant, per day, per metric. Most dashboards only need these.
- Materialized views for heavier aggregations. In PostgreSQL, REFRESH MATERIALIZED VIEW CONCURRENTLY lets reads continue during a refresh, but only if the view has at least one unique index on plain columns with no WHERE clause; without it, a refresh can block readers.
- A columnar analytics database when event volumes reach hundreds of millions of rows and rollups are no longer enough.
CREATE MATERIALIZED VIEW daily_tenant_metrics AS
SELECT tenant_id,
date_trunc('day', paid_at)::date AS day,
count(*) AS invoices_paid,
sum(amount_cents) AS revenue_cents
FROM invoices
WHERE status = 'paid'
GROUP BY tenant_id, date_trunc('day', paid_at)::date;
-- Required for CONCURRENTLY: a unique index on plain columns, no WHERE clause.
CREATE UNIQUE INDEX daily_tenant_metrics_pk ON daily_tenant_metrics (tenant_id, day);
-- Run from a scheduler, for example every 15 minutes.
REFRESH MATERIALIZED VIEW CONCURRENTLY daily_tenant_metrics;
Tell customers how fresh the numbers are ("updated every 15 minutes") on the dashboard itself. Most support tickets about wrong numbers are really about stale numbers nobody explained. Row-level security applies to tables, not materialized views, so do not grant the reader role the view itself: copy its rows into a normal table with a policy, such as tenant_daily_rollups above, or expose it only through your own tenant-filtered API.
What does building fixed dashboards yourself involve?
For level 1, an endpoint per metric that reads the rollup for the session's tenant and a date range, a charting library in the front end, and a caching layer. The code is small; the work is in definitions. "Active user", "revenue" and "churned" each need one agreed definition, documented, or customers will compare your chart with their own spreadsheet and lose trust.
Build effort grows with each new requirement: CSV export, scheduled emails, timezone handling per tenant, currency conversion, comparison periods, and permissions on which users see which reports. When the list of requested reports keeps growing, that is the signal to embed instead. The same build-or-buy reasoning for internal screens is in SaaS admin panel: build vs buy.
Do-it-yourself estimate: 1–2 weeks for 5–10 fixed charts on rollup tables with tenant isolation, export and tests; 1–3 weeks to embed a BI tool properly, including signed tokens, a read-only role, theming and isolation tests. The main risk on either route is a tenant leak through a parameter the browser can change.
Can analytics be a paid add-on?
Often, yes. Advanced reporting is a common higher-plan or add-on feature, and Stripe even lists "advanced reporting" among its example features in the Entitlements docs. Gate the analytics routes and embed-token endpoint with the same entitlement check as other paid features, described in SaaS entitlements and plan limits. If you embed a tool with per-viewer pricing, this also keeps that bill tied to customers who pay for it. Running costs belong in your unit economics; see what a SaaS costs to run per month.
Buy, build or hire?
| Option | Examples | Choose this when | Watch out for |
|---|---|---|---|
| Embedded BI tool | Metabase Pro or Enterprise, other embedded BI products | Customers want self-service exploration and custom reports (level 3) | Per-user or per-viewer pricing at your customer scale; theming limits; another processor for customer data |
| Open-source BI or a semantic layer | Metabase open source with guest embeds, Cube with your own front end | You want control and lower licence cost, and have developers to run and theme it | Hosting, upgrades and security patches are yours; SSO embedding may need a paid plan |
| Custom-built dashboards | Rollup tables, metric endpoints and a charting library | A fixed set of charts that must match your product exactly (level 1) | Every new report is development work; export, scheduling and timezones add up |
| Hire a team to build it | RAITHub or another studio | You need rollups, tenant isolation and either route done properly, and your team is on the core product | Get metric definitions and isolation tests in the handover, not only charts |
How do you test customer-facing analytics?
- Isolation: tamper with every parameter and token as tenant A and confirm tenant B's numbers never appear; replay an expired embed token and expect refusal.
- Correctness: seed known data and assert each metric's value, including edge days around midnight in the tenant's timezone.
- Freshness: after a new record, check it appears within the stated refresh window.
- Load: run the heaviest report for a large tenant and check the main app's response times do not move.
- Entitlements: a tenant without the analytics add-on gets a refusal from the API, not just a hidden menu item.
Why RAITHub for this
- Dashboards on real business data. RAITHub's client work includes a fintech dashboard; TheSkinProof, the founder's own venture rather than a client, runs 5 portals on 217 API endpoints.
- Tenant isolation in the database. Sundor Skin uses row-level security across 146 PostgreSQL tables, with 88 permission codes and 530+ tests; BlockEstate is multi-tenant.
- Database cost awareness. This site's own Neon cost fix shows the attention to database load that analytics workloads need.
RAITHub has not published a case study of an embedded BI integration; the guidance here is engineering practice, not a client result.
When you don't need us
- You need three KPIs on a home screen. One query per metric and a charting library will do.
- Customers already export to their own BI tool. A good CSV export or a read-only API may be all they want.
- You want developers placed in your team. RAITHub does fixed-scope builds and dedicated teams, not staff augmentation.
How RAITHub would build this
- Metric definitions first: each number written down and agreed before any chart is drawn.
- Data layer: rollup tables or materialized views, a read replica if needed, and refresh jobs with stated freshness.
- Isolation: server-set tenant, signed short-lived embed tokens, a read-only role and row-level security.
- Front end: custom charts in your design system, or an embedded BI tool themed to match, gated by plan entitlements.
Timeline: inside a new product, part of the 4–6 week fixed-scope SaaS build; added to an existing product, it fits within the 6–12 week backend range alongside other work, with exact scope in the quote.
You receive: isolation and correctness tests in CI, metric definitions, handover docs and runbooks, and full IP assigned to you under NDA.
Next step: a free 15-minute technical audit, then a written fixed quote. See the SaaS development service, or book the audit.
Frequently asked questions
What is embedded analytics in SaaS?
Dashboards and reports about each customer's own data, shown inside your product. It can be built in-house or provided by embedding a BI tool, and every query must be limited to the viewing customer's data.
Is it cheaper to build or buy embedded analytics?
For a few fixed charts, building is usually cheaper. For self-service reporting, embedding is usually cheaper than rebuilding a query builder, but check per-user or per-viewer pricing against your real customer user counts.
Can I use Metabase open source for customer-facing dashboards?
Metabase's embedding docs say guest authentication and public embeds work on all plans, including open source. SSO-based embedding requires a Pro or Enterprise plan.
How do I stop customers seeing each other's data in embedded dashboards?
Set the tenant on your server inside a signed, short-lived token that the browser cannot change, and add database row-level security for the analytics role as a second layer.
Should analytics run on my production database?
Not on live tables once data grows. Use a read replica, rollup tables or materialized views so heavy reports cannot slow the core product.
How fresh should customer dashboards be?
Most customers accept data that is minutes old if you say so on the screen. Real-time numbers cost far more to build and run, so offer them only where a decision depends on them.
Related posts
Ready to discuss your project?
Book a free 15-minute technical audit with our engineering team.