[SIP-221] Selective Per-Audience Dashboard Versions for Embedded Multi-Tenant Deployments
- Dominant language
- Python
- Stars
- 74.8k
- Forks
- 18.3k
- Avg merge
- 2d 5h
- Merged PRs (30d)
- 685
Description
*Please make sure you are familiar with the SIP process documented* [here](https://github.com/apache/superset/issues/5602). The SIP will be numbered by a committer upon acceptance.
## [SIP] Proposal for Selective Per-Audience Dashboard Versions for Embedded Multi-Tenant Deployments
> **Note on scope vs. existing versioning SIPs.** This is **not** a version-*history* feature. [SIP-210] Entity Version History (#39492), [SIP-203] Git-backed dataset version control (#37427), [SIP-163] Archiving (#33044), and [SIP-208] Soft delete (#39464) all operate on a **history axis** — recovering/restoring a *past* state of *one* object, where exactly one version is live at any instant. This SIP proposes a **parallel-variants axis**: multiple versions of a dashboard (and its charts/datasets) that are **live concurrently**, each pinnable to a specific audience (tenant / guest token / embed), indefinitely, until that audience is migrated.
### Motivation
In embedded, multi-tenant Superset deployments, a single Superset instance serves many tenants who each view the "same" dashboard through a guest token scoped by row-level security. When the embedding application ships changes on a **rolling basis** (one tenant at a time), the dashboard must evolve *in lockstep* with each tenant's backend — a new chart or a dataset SQL change frequently depends on schema/data that only already-migrated tenants have.
Today there is **no way to serve two different live versions of a dashboard (and its charts/datasets) to two different tenants at the same time.** Because dashboards, charts, and datasets are shared, mutable, single-state objects, editing a chart or a dataset's SQL immediately changes what **every** tenant embedding that dashboard sees. This breaks not-yet-migrated tenants (queries reference columns/data they don't yet have), and makes safe gradual rollout impossible.
Concretely, a dashboard is only a layout container; the substance lives in **chart** and **dataset** objects. Two dashboards that reference the same charts/datasets are two *views of one version*, not two versions — so "point tenant A at dashboard v2 and tenant B at v3" is not expressible natively.
This is the embedded-analytics analogue of a canary / blue-green rollout, and it is a common requirement for teams running Superset as the BI layer of a multi-tenant SaaS.
### Proposed Change
Introduce a first-class notion of a **dashboard version (variant)**:
1. **Version = an immutable, independently-addressable snapshot of an entire object graph** — the dashboard plus the charts and datasets it depends on — sharing only the database connection (a connection is neither version- nor tenant-specific).
2. **Version selection per embed / per guest token** — e.g. a `version` claim in the guest token, or an embedded-UUID that resolves to a specific version — so tenant A can render v2 while tenant B renders v3 **simultaneously and indefinitely**.
3. **Lifecycle for gradual rollout** — create a new version from the current one, roll audiences onto it incrementally, and retire an old version once no audience references it.
A pragmatic minimum viable primitive that unlocks most of the value without new serving semantics: **first-class tooling to atomically clone a full dashboard graph (dashboard + charts + datasets) under fresh UUIDs as a named version.** Superset's `assets/import` already keeps object graphs with distinct UUIDs fully isolated, so an atomic "clone entire graph as version N" operation (plus a per-embed version pointer) is sufficient to serve parallel versions safely.
### New or Changed Public Interfaces
- **Model:** an optional `version`/`variant` concept associating a dashboard with a version label and a self-contained set of charts/datasets (or a lightweight `versions` grouping over cloned graphs).
- **REST:** endpoints to (a) clone a dashboard's full graph into a new version, (b) list versions of a dashboard, (c) retire/delete a version, (d) resolve/serve a specific version for a given embedded UUID / guest token.
- **Guest token / embedding:** an optional `version` selector in the embedded-dashboard resolution path so a single logical dashboard can be served as different versions to different guest tokens.
- **CLI / import-export:** support exporting/importing a specific version's graph as an isolated bundle.
- No change required to existing single-version behavior; the feature is opt-in.
### New dependencies
None anticipated. The proposal builds on existing import/export (`assets/import`), embedding, and RLS machinery.
### Migration Plan and Compatibility
- Backward compatible and opt-in: dashboards without versions behave exactly as today.
- Requires a metadata migration to introduce the version grouping/pointer and (optionally) a per-embed version selector; existing dashboards map to an implicit "current" version.
- RLS: because each version can own its own datasets, RLS rules that reference datasets must be able to span a dashboard's live versions (e.g. a tenant-isolation rule covering every live version's datasets).
### Rejected Alternatives
1. **Rotating only the dashboard UUID between two "slot" dashboards.** Fails because the two dashboards share the underlying chart/dataset objects — editing content mutates both, so un-migrated tenants still break. Rotation is cosmetic unless the *entire* graph is separated.
2. **Relying on SIP-210 / SIP-203 (history/restore).** These recover past states of a single live object; they cannot serve multiple versions concurrently to different audiences.
3. **Hand-rolled separate object graphs per version (current workaround).** We give each version's dashboard/charts/datasets version-unique UUIDs (sharing only the DB connection) and pin each tenant via its embedded dashboard UUID. It works but is entirely manual: UUID remapping across export bundles, manual version retirement, and a shared RLS rule that accumulates every version's datasets. First-class support would remove this fragile glue for anyone doing embedded multi-tenant rollouts.
Contributor guide
Research direction
Start by reading the existing assets/import flow, embedded-dashboard resolution path, guest-token handling, and RLS machinery described in the proposal. Map how dashboard, chart, and dataset object graphs are currently isolated, then define the model, REST, embedding, and import/export boundaries needed for named parallel versions; done requires an accepted design that preserves existing single-version behavior.
Written by the indexing model from the issue text.
Assessment
- Tech stack
- python, react, sql
- Domain
- api, authentication, backend-api-design, databases
- Issue type
- Feature
- Difficulty
- 5/5
- Estimated time
- Over a week
- Activity status
- Quiet
- Clarity
- Mostly clear
- Newbie friendliness
- 30/100