Embedding Apache Superset dashboards directly inside a SaaS application — known as embedded analytics — lets you offer customers personalized visualizations without reinventing the wheel. Since version 2.0, Superset ships with an official embedded SDK and a guest token system that make integration secure and smooth. This guide explains the architecture, the code, and the pitfalls to avoid in 2026.
1. Why embed Superset rather than build your own dashboards?
Building an in-house analytics module from scratch is a heavy engineering project: chart library choice, data connections, multi-tenant security, performance, drill-down, exports… Embedding Apache Superset solves 90 % of these problems in a few days of integration.
If you want to avoid the hosting friction and focus on product integration, TVL Managed Superset deploys a ready-to-use instance in less than 3 minutes, with the embedded SDK enabled by default.
Concrete benefits of embedding
- 30+ visualization types out of the box (time series, maps, sankey, big number, etc.);
- SQL Lab, RLS, dynamic filters, cross-filtering, alerts, exports — all included;
- Outsourced maintenance: security patches come from the upstream project;
- Time-to-market 5 to 10 times faster than custom development.
2. The three integration approaches
2.1 Simple iframe (not recommended in production)
The naive approach: point an <iframe> to a public Superset URL. Simple, but it exposes your full instance and prevents fine access control. Reserved for fully public dashboards. See also Superset public dashboards.
2.2 Official embedded SDK (recommended)
Since Superset 2.0, the project ships an official JavaScript SDK on npm as @superset-ui/embedded-sdk. It combines a backend guest token system and a frontend rendering component. This is the standard approach for 2026.
2.3 REST API + custom frontend
For highly tailored cases, you can consume the Superset REST API and rebuild your own rendering. Costly but flexible.
3. Embedded SDK architecture
The canonical architecture relies on three actors and a token flow:
- The client app (your SaaS) asks its backend for a guest token specific to the current user.
- The SaaS backend calls the Superset API
/api/v1/security/guest_token/with an authenticated service account, passing a payload describing the guest user, allowed resources, and RLS filters to apply. - The frontend SDK receives the token and uses it to fetch the dashboard HTML/JS from the Superset instance, with a limited and signed session.
The guest token is a short-lived JWT (5 to 15 minutes typically). It carries permissions and expires — it is the central element of the security model.
4. Preparing your Superset instance
4.1 Enable the feature flag
In superset_config.py, add:
FEATURE_FLAGS = {
"EMBEDDED_SUPERSET": True,
}
GUEST_ROLE_NAME = "Public"
GUEST_TOKEN_JWT_SECRET = "<robust secret key>"
GUEST_TOKEN_JWT_ALGO = "HS256"
GUEST_TOKEN_JWT_EXP_SECONDS = 300
4.2 Configure CORS and CSP
Allow your SaaS application origin in HTTP_HEADERS and TALISMAN_CONFIG. Add your domain in frame-ancestors of the CSP, otherwise browsers will block the iframe.
4.3 Make a dashboard "embeddable"
In the Superset UI, open the dashboard, go to "… → Embed dashboard", add the allowed domains and note the UUID that appears. This UUID is what you pass to the SDK.
5. Backend code (Node.js example)
// pages/api/superset/guest-token.js
import fetch from 'node-fetch';
export default async function handler(req, res) {
const { user, dashboardUuid, tenantId } = req.session;
// 1. login Superset service account
const loginRes = await fetch('https://superset.example.com/api/v1/security/login', {
method: 'POST',
headers: { 'Content-Type': 'application/json' },
body: JSON.stringify({
username: process.env.SUPERSET_SVC_USER,
password: process.env.SUPERSET_SVC_PWD,
provider: 'db',
}),
});
const { access_token } = await loginRes.json();
// 2. request guest token with dynamic RLS
const guestRes = await fetch('https://superset.example.com/api/v1/security/guest_token/', {
method: 'POST',
headers: {
'Content-Type': 'application/json',
Authorization: `Bearer ${access_token}`,
},
body: JSON.stringify({
user: { username: user.email, first_name: user.firstName, last_name: user.lastName },
resources: [{ type: 'dashboard', id: dashboardUuid }],
rls: [{ clause: `tenant_id = '${tenantId}'` }],
}),
});
const { token } = await guestRes.json();
res.status(200).json({ token });
}
6. Frontend code (React example)
import { embedDashboard } from '@superset-ui/embedded-sdk';
import { useEffect, useRef } from 'react';
export function DashboardEmbed({ dashboardUuid }) {
const ref = useRef(null);
useEffect(() => {
embedDashboard({
id: dashboardUuid,
supersetDomain: 'https://superset.example.com',
mountPoint: ref.current,
fetchGuestToken: async () => {
const res = await fetch('/api/superset/guest-token', { method: 'POST' });
const { token } = await res.json();
return token;
},
dashboardUiConfig: {
hideTitle: true,
hideTab: false,
filters: { expanded: true },
},
});
}, [dashboardUuid]);
return <div ref={ref} style={{ width: '100%', height: '800px' }} />;
}
7. Multi-tenant security: the key to embedding
7.1 Dynamic Row Level Security (RLS)
In the guest token payload, the rls field injects an SQL filter applied to every dataset referenced by the dashboard. This is the critical point: each token is forged for a given tenant, and the filter tenant_id = 'X' guarantees that the user will never see other customers' data.
7.2 Mandatory backend validation
Never trust a tenantId sent by the frontend. The tenant must be derived backend-side from the authenticated session, otherwise you open the door to trivial privilege escalation.
7.3 Limit the guest role's scope
The Public role used by the SDK must be restricted to the strict minimum: only datasets explicitly required by embedded dashboards, never SQL Lab access, no export rights unless needed. See Roles and permissions in Apache Superset.
8. Performance and UX
- Redis cache enabled to serve frequent queries without hitting the database;
- Async queries via Celery for long queries (>5 s);
- Pre-aggregation in the source (materialized views, ClickHouse, or DuckDB);
- Lazy-load dashboards below the fold of your app;
- Theme alignment: override Superset CSS to match your brand (white-label, see white-labelling Superset).
9. Common pitfalls in production
- Forgotten CORS: blank iframe, console full of errors. Check allowed domains.
- JWT secret too short: API returns 401. Use 64+ random characters.
- RLS filtering on a nonexistent field: query crashes in SQL. Test with a minimal dataset first.
- Expired token client-side: implement a retry with re-fetch in
fetchGuestToken. - Missing CSP
frame-ancestors: Chrome blocks silently. - Superset rate limit: under heavy traffic, put an HTTP cache in front of the API and Redis behind.
10. Summary table
| Aspect | Recommendation |
|---|---|
| Method | Official embedded SDK (npm @superset-ui/embedded-sdk) |
| Auth | JWT guest token, 5 min duration, dynamic RLS |
| Multi-tenant | tenant_id from backend session, injected RLS filter |
| Domain | Dedicated subdomain + strict CORS + CSP frame-ancestors |
| Performance | Redis cache, Celery async queries, source pre-aggregation |
| Hosting | Dedicated instance recommended for SaaS production |
11. Conclusion
Superset embedding has matured in 2026: an officially maintained SDK, a battle-tested security model based on guest tokens, performant RLS. For a SaaS that wants to offer a strong analytics feature without building its own BI stack, this is the fastest and safest path.
Want the benefits of Apache Superset without the friction of installation and maintenance? Deploy your instance in 3 clicks with TVL Managed Superset, hosted in Europe (OVHcloud, Roubaix), embedded SDK preconfigured and dedicated instance available for SaaS production.
To go deeper, also read white-labelling Apache Superset, iframe integration and the official embedding documentation.