12 min read

Embedding Superset without iframes

a microfrontend architecture that runs in the host DOM

The iframe SDK hits a structural wall: theming, SSO, cookies, filters, speed. Here is the microfrontend architecture we run in production instead — single-spa, same-origin proxy, real session auth — including the honest trade-offs.

Embedding Superset without iframes — a single-spa microfrontend architecture (social preview)
By Rt Kazakov· Founder · Drafted

The official Apache Superset embedding SDK isolates dashboards inside a sandboxed cross-origin iframe. We documented how that machinery works and the six structural pain points it produces — theme flashes, SSO collisions, dead third-party cookies, trapped filter state, 15-second loads, and admin links leaking to customers. All six share one root cause: the iframe is a wall.

Rt Kazakov@RtKazakovAll six have one root cause: the iframe is a wall, and your product lives on the other side of it.X logoView on X

This article describes the alternative we run in production: Superset compiled as a true microfrontend that mounts natively inside the host document's DOM, execution context, and routing lifecycle. No iframe, no guest tokens, no second authentication system.

The architecture

Superset's core visualization and routing engines are compiled as a decoupled JavaScript bundle and registered as a native child application — in our case via single-spa:

import { registerApplication, start } from "single-spa";
 
registerApplication({
  name: "superset-dashboard-plugin",
  app: () => System.import("https://cdn.example.com/supersetDashboardPlugin.js"),
  activeWhen: "/app/analytics",
  customProps: {
    originUrl: "/superset", // same-origin reverse proxy route
    businessId: "tenant_987",
    basename: "/app/analytics",
    navigation: {
      showNavigationMenu: true,
      base: "/app/analytics/",
    },
  },
});
 
start();

When the user navigates to /app/analytics, the host framework mounts the Superset engine straight into a DOM container. The plugin boots in the host thread, picking up the existing stylesheets and utilities. All the backend calls go through the same-origin proxy, so the browser just sends the user's real session cookies without any extra dance.

The build is based on our maintained fork (upstream base 4.1.1), compiled with a dedicated webpack plugin configuration into versioned, CDN-hosted artifacts.

Iframe SDK vs microfrontend, side by side

DimensionIframe SDKMicrofrontend
Integration modelIsolated <iframe> containerReact app mounted natively via single-spa
AuthenticationHost SSO plus temporary guest JWTsSame-origin passthrough of the host session cookies
RLS resolutionSynthetic anonymous guest roleReal authenticated user's OAuth/JWT claims
ThemingBlocked by the origin wall; loading flashesNative theme provider applied at bootstrap
Filter & URL syncTrapped inside the iframeSynced with the host router's history
NavigationEach dashboard loaded and authorized individuallyMulti-dashboard folder navigation, managed server-side
PerformanceFull HTML/JS reload per dashboard switchClient-side React route change; bundles load once
ExtensibilityClosed black boxAdmin and edit surfaces stripped at compile time

How this resolves each pain point

Theming without the flash. Running in the parent document's thread, brand parameters — colors, typography — merge with Superset's internal styling tokens at bootstrap, through a native Ant Design theme provider. Per-brand style schemas handle multi-tenant branding. Chrome, charts, tooltips, and the filter bar render in the product's style on first paint. No postMessage, no flash.

One authentication system, not two. The EMBEDDED_SUPERSET flag stays off; guest tokens don't exist in this architecture. The client routes all API calls through the same-origin proxy, the browser attaches the existing session cookies and CSRF token, and a custom Flask security manager on the Superset side maps the real user's OAuth/JWT claims to roles. Row-level security derives from the actual authenticated identity, not a synthetic guest role.

Insulated from the cookie apocalypse. All API traffic targets the parent application's own domain, so cookies are first-party by construction. Talisman, CSP, and X-Frame-Options conflicts disappear because nothing is framed.

Filters live in the URL. Filter selections sync with the parent router's query string via standard native_filters_key mappings. Users deep-link to filtered views, bookmark analytical workspaces, and use the browser's back and forward buttons like in any part of your product.

Dashboard switches are route changes. The heavy core bundles download once, at initial page load. Switching dashboards triggers a client-side re-render plus a metadata fetch — not a full application bootstrap behind an iframe:

Iframe SDK dashboard switch:
[click] → create iframe → load wrapper HTML → download full JS bundle
        → auth handshake → render
 
Microfrontend dashboard switch:
[click] → React route change → fetch metadata → render
Rt Kazakov@RtKazakov5. Speed. Every dashboard switch = full app reload inside the frame: HTML + the entire Superset React bundle + auth handshake. Cold loads hit 15–30s without serious Redis work.X logoView on X

A curated, read-and-interact surface. Admin tools, edit controls, SQL Lab, and chart design interfaces are excluded from the bundle at compile time — not hidden with CSS. Which dashboards each user sees is managed through server-side folders, so product teams change the catalog without shipping a frontend release. (Persistent saved views work here too — filter presets run inside the embedded plugin through the same REST API.)

The honest trade-offs

This approach is not free, and pretending otherwise would be a disservice.

Tighter runtime coupling. An iframe sandboxes crashes; a microfrontend shares the host page's thread. Memory leaks, uncaught exceptions, or global CSS pollution inside the plugin can affect the parent application. The host has to wrap the plugin in real React error boundaries.

Dependency alignment. Host and plugin must share compatible React versions; peer dependency conflicts are real integration work.

You are maintaining a fork. This requires a single-spa-compatible fork of the Superset frontend and a build-and-deploy pipeline that compiles and distributes versioned JS artifacts on every upstream release. That is an ongoing engineering commitment — it is the one we took on so our clients don't have to.

Use-case alignment. For internal visualizations, public dashboards, or simple low-concurrency reports, the standard iframe SDK remains a practical, low-friction tool. The microfrontend pays off when embedded analytics is a core product feature demanding deep white-labeling, native routing, performance, and a single security model.

The bottom line

The iframe SDK is an excellent prototyping tool that hits a structural wall in production-grade products. Mounting Superset natively in the host DOM — same-origin auth, host routing, compile-time curation — removes the wall rather than configuring around it.

A live demo of the production build runs on the Superset Embedded page. If you are evaluating iframe-less embedded analytics for your product, talk to our platform engineering team.

Topics

  • Apache Superset
  • Embedded analytics
  • Microfrontend
  • single-spa