Skip to content

Migration Plans

Jannis Schreiber edited this page Jul 9, 2025 · 8 revisions

Migration plans allow you to program a series of steps to export data from a source org and import this data to a target org.

⚠️ The plugin currently only supports data export.

Configuring a Plan

A plan consists of a name and an ordered list of objects to export. The most simple plan exports a single object with a simple query:

name: Simple Test Plan
objects:
  - objectName: Account
    queryString: SELECT Id,Name FROM Account

In reality, plans can include multiple objects, export ids and make them available to other queries:

name: Test Data Export Plan
objects:
  - objectName: Account
    queryString: SELECT Id,Name FROM Account WHERE Type = 'Civilian Ship'
    exports:
      Id: testAccIds
  - objectName: Contact
    query:
      fetchAllFields: true
      bind:
        field: AccountId
        variable: testAccIds
    exports:
      Id: contactIds
  - objectName: Order
    query:
      fetchAllFields: true
      bind:
        field: AccountId
        variable: testAccIds
  - objectName: Opportunity
    query:
      fetchAllFields: true
      bind:
        field: ContactId
        variable: contactIds

Define the Query

...

Exports and Parent Binds

This syntax allows to execute similar functionality like the common WHERE Id IN :accIds syntax from Apex. Due to technical limitations, the query plan only allows to bind a single variable, not multiple ones (something like WHERE Id IN :accIds AND OwnerId IN :ownerIds is not possible).

Simple Exports Syntax

An export consists of a simple key-value pair: FieldApiName and localVariableName. You can configure multiple exports per object. You need to make sure, that the exports are also included in the query.

- objectName: Account
  exports:
    Id: accIds
    OwnerId: myAccOwners
    ParentId: parentAccIds

You can select the following field types for export: Id (id), Lookup (reference), String (string), and Number (int).

Export Tooling API Objects

Tooling API objects are supported out-of-the-box. Simply add the isToolingObject to the object definition.

- objectName: FlexiPage
  isToolingObject: true
  queryString: SELECT Id,DeveloperName FROM FlexiPage

Beware, that too many metadata objects have a FullName property that is only supported, if the query is limited to one row. Use the queryString and explicitly set fields for retrieval.

Merge Multiple Exports

It is possible to export different fields (also from different objects) to the same variable. This is useful, if you plan to use the variable to filter a polymorphic Lookup-field such as Task.WhatId or ContentDocumentLink.LinkedEntityId.

- objectName: Account
  exports:
    Id: linkedEntityIds
- objectName: Case
  exports:
    Id: linkedEntityIds

Binding Exports

After a variable has been exported, it is available to all objects that are queried after it. You simply need to bind it in the query of the object. This feature can only be used, if you construct the query string dynamically (it cannot be used with queryFile or queryString.

- objectName: Contact
  query:
    fetchAllFields: true
    bind:
      field: AccountId
      variable: myAccIds

Running an Export

Once your plan is configured, you should quickly validate it against the source org. This command will try to resolve all objectNames in your plan, verify that bound parent ids are exported before using them, and that all query strings resolve to valid SOQL.

sf jsc data export -p my-test-plan.yaml -o MyProductionOrg --validate-only

Then, run it. The default output directory is an exports/plan-name folder in your project root.

sf jsc data export -p my-test-plan.yaml -o MyProductionOrg

Clone this wiki locally