Lifecycle: export, import & restore
Dashboards, data models and governed metrics can leave a workspace as definitions — portable JSON artifacts with no data and no credentials in them — and be imported into another workspace. Alongside that, dashboards carry immutable version snapshots, a field-level diff, and a restore. Together they cover the dev → prod path: build in one workspace, export, import, promote, and roll back if it goes wrong.
Export a definition
Section titled “Export a definition”Every list page has an export affordance:
| Where | Control |
|---|---|
| Dashboards list | a download icon on the card (hover) — accessible name Export <name> |
| Data Models list | a download icon on the row (hover) — accessible name Export <name> |
| Metrics hub | an Export button on the row (hover) |
You get a lowercase, filesystem-safe name with spaces and punctuation replaced
by hyphens: <name>.<assetType>.json, for example
q3-revenue.dashboard.json.
What is (and isn’t) in a definition
Section titled “What is (and isn’t) in a definition”This is the part that matters most, so be precise about it. An exported artifact contains no data, no credentials, and no workspace IDs. Every binding to something workspace-local is replaced by a symbolic reference:
| Reference | Means |
|---|---|
$model:0, $source:0, $metric:0 |
a positional reference — you map it to a real object at import |
$field:{tableAlias}.{fieldName} |
a model field, resolved by name in the target model |
$table:{tableAlias} |
a model table, resolved by alias |
$measure:{name} |
a SquareX measure, resolved by name |
The positional references are listed in the artifact’s references block with
their original names, so the import screen can show you “Orders Model”
rather than a bare token.
Serialization is deterministic — sorted keys, no timestamps, and symbolic references instead of workspace-local UUIDs — so the same unchanged asset exports byte-identical every time. That is what makes these files git-diffable: commit them, and a pull request shows exactly what changed.
Dashboard artifacts also embed definitions for dashboard-bound saved queries (name, SQL, description, and a symbolic source reference). Import recreates those queries with fresh IDs before it creates the cards, so saved-query cards do not arrive as “Not configured.”
Import a definition
Section titled “Import a definition”Click Import on the Dashboards, Data Models or Metrics list. The Import definition dialog opens.
- Paste the JSON into Exported artifact (paste the JSON, or choose a file), or pick the file with Artifact file. Invalid JSON shows “Not valid JSON yet.”
- As soon as the JSON parses, the Map references to this workspace
section appears — one row per positional reference, labelled with its
original name (e.g.
Orders Model (model),Prod Postgres (source)). Pick the matching object in this workspace from each dropdown (they start at choose…). - Optionally press Check — a dry run that resolves everything without writing, and reports anything it couldn’t match.
- Press Import.
Import stays disabled until every required reference is mapped. Mapped IDs are validated against the current workspace, so you cannot graft an asset onto another tenant’s model.
The API has an allowUnresolvedFields escape hatch, but the web dialog does
not expose it. In the UI, unresolved $field, $table, or $measure
references block the real import after Check reports them.
What import does, and what it does not
Section titled “What import does, and what it does not”Import creates a new asset. It does not update, merge into, or overwrite an existing dashboard, model or metric. Treat the artifact as the source of truth and the import as a deploy of a new object, not an in-place upgrade.
Metric names are unique per workspace, so a collision is different: Check
reports the conflict and the dialog proposes <name> (imported). Choose a
different name before importing. Dashboard and model imports still mint a new
asset rather than updating one with the same name.
Once the positional refs are mapped, fields, tables and measures resolve by name against the target model. If the target model’s aliases and field names match the origin’s, everything binds. If they don’t, you get an amber warning — “Unresolved in the mapped model (aliases/field names must match):” — with the list. Fix the target model’s naming, or re-export from a workspace that matches.
Versions, diff & promotion
Section titled “Versions, diff & promotion”Open a dashboard in the editor and expand the Deployment Pipeline strip at the bottom. (It’s hidden in preview mode, and needs edit permission.)
Publish New Version snapshots the dashboard — name, description, layout, theme, filter state, pages, cards and filters — as an immutable version. The strip shows the current version number and whether it’s Published or Draft — publish to deploy, plus the Version History (latest 10).
The diff
Section titled “The diff”The diff compares two snapshots field by field and reports one entry per changed leaf, with readable paths — cards and filters are matched by ID but labelled by title, so you read:
cards."Revenue by month".chartSpec.yFields[0].aggregation sum → avgThe summary counts + added, − removed, ~ changed, and an unchanged comparison says “No differences — the two versions are identical.”
You reach it from four places:
| Control | Compares | Gates anything? |
|---|---|---|
Changes since v{n} |
the published version → your working state | no — preview |
| diff (per version row) | the previous version → that version | no — preview |
Promote to {stage} |
the version already on the stage → the one you’re promoting | yes — see below |
| restore | your working state → the version you’re restoring | yes — it’s the confirm step |
Promotion
Section titled “Promotion”Promote to {stage} deploys a version to the next stage in your pipeline
(auto-publishing first if that stage requires it). When the target stage
already has a different version deployed, the diff opens first as a
confirmation — you see exactly what the promotion would change, and the deploy
only fires when you confirm Promote v{n} to {stage}.
Stages are workspace-configurable, and a version can be deployed to any stage
directly (Deploy v{n}) or removed from one. Rolling a stage back is just
deploying an older version to it.
Restore
Section titled “Restore”In Version History, every version other than the current one has a
restore link. Clicking it opens the diff — your working state on the left,
that version on the right — and the confirm button reads
Replace working state with v{n}.
Restore replaces the dashboard’s working state with the snapshot (keeping the original card and filter IDs), then auto-publishes, so the restore is itself a new version. Nothing is lost: the history records that the new version was restored from the old one, and you can restore back out of it.
Restore a data model
Section titled “Restore a data model”Publishing a data model now stores a real definition snapshot. Open the model’s Version History and choose Restore on an older version to put its tables, relationships, fields, measures and policies back into the working definition. Existing IDs are preserved where possible so dashboard cards, filters and data-quality tests keep their bindings.
Model restore does not publish automatically and does not create another version. Review the restored working definition, validate it, and publish it when it is ready; that publish creates the next snapshot. The restore runs in one transaction and reconciles tables, fields, relationships, hierarchies, RLS policies, measures, and table transforms in dependency-safe order.
Version history starts with the first publish made after snapshot versioning was introduced; older version numbers do not have a snapshot to restore. The current model dialog executes Restore directly—there is no model diff or second confirmation step.
Honest limits
Section titled “Honest limits”- Field-level diff, promotion stages and auto-publishing restore remain dashboard-only. Models have snapshot history and restore, but no promotion pipeline or pre-restore field diff. Metrics still have no version restore.
- Import always creates. There is no “update this existing dashboard from this artifact” path.
- Fields resolve by name, so renaming a field in the target model breaks imports that referenced it.
Related
Section titled “Related”- Data models & relationships — publishing and versioning a model.
- Canvas basics — where the Deployment Pipeline strip lives.
- Catalog: certification & glossary — lineage and impact analysis before a change.