Migrate a dashboard between projects
Use the export/import flow when:
- Promoting a dashboard from a
devproject toprod - Cloning a working dashboard for a new tenant
- Backing up a dashboard before a risky restructure
Export
Source dashboard → ⋯ menu → Export → JSON. The browser downloads <dashboard-slug>.dashboard.json. The file contains:
- Dashboard metadata (title, description, layout, theme)
- Every tile's full configuration (query, vis settings, filter bindings)
- Filter and parameter definitions
- Default values for filters
- Reference IDs for upstream datasets and connections
What it does not contain:
- The data itself — the JSON references datasets by ID, not by content
- Permissions and sharing — these are recreated empty on import
- Scheduled exports — recreate manually
- Comments, view counts, or any audit history
Import
Target project → New dashboard → Import → JSON. Upload the file. The importer walks the JSON and resolves dataset references against the target project:
| Source state | Target state | What happens |
|---|---|---|
| Dataset by name + matching schema | Dataset exists in target | Auto-resolves to the target's dataset |
| Dataset by name + schema mismatch | Dataset exists but column changed | Import surfaces a "schema diff" prompt; you map the missing/renamed columns or skip the affected tile |
| Dataset by name | Dataset doesn't exist | Tile is imported but disabled — fix by either creating the dataset in the target or rebinding the tile to a different dataset |
| Connection reference | Connection doesn't exist | Import asks you to pick or create a connection in the target before continuing |
Common gotchas
Dataset IDs differ across projects — even datasets with the same name have different UUIDs. The importer resolves by name+schema by default. If two datasets in the target match by name, the importer asks you to disambiguate.
Filters bound to specific values — if a filter defaults to "Region = Jakarta" but the target dataset has no "Jakarta" value (different region naming), the filter renders empty. Override the default in the import dialog or fix it post-import.
dbt model references — dashboards built on dbt models reference the model by its fully-qualified name (schema.model). If the target project has dbt under a different schema, run a search-and-replace on the JSON before importing, or duplicate the dbt project structure.
Embedded queries with hardcoded IDs — an embedded SQL tile that includes WHERE project_id = 17 in literal SQL won't auto-rewrite. Audit your tiles for hardcoded IDs before exporting.
Bulk migrations
For migrating 10+ dashboards at once, the Project clone action (admin → Projects → Clone) is more reliable than 10 individual import/exports. It atomically duplicates dashboards + datasets + connections + flows in dependency order, with a single "what changed" diff at the end.
Project clone needs org.admin.
See also
- Restore a deleted dashboard — when migrate ≠ what you want
- Connections vs Connectors — disambiguates the import-resolution surface