Migration
A migration definition describes how data should be imported from a legacy system into the platform. It is published via GET /metadata/{tenantId}/migrationDefinition and consumed by an external migration tool that performs the actual import.
MigrationDefinition
{
"migrationType": "MyLegacyERP",
"parameters": [
{ "name": "apiUrl" },
{ "name": "apiKey" }
],
"steps": [...],
"valueMap": {
"MALE": "male",
"FEMALE": "female"
},
"mnRelations": [...]
}
| Property | Type | Description |
|---|---|---|
migrationType | string | Identifier of the legacy system (e.g. "MyLegacyERP"). |
parameters | ValueType[] | Configuration parameters the migration tool needs (e.g. API URL, credentials). |
steps | MigrationStep[] | Ordered list of entity mappings. Each step maps one legacy entity type to a target class. |
valueMap | object | Global value substitutions applied across all steps. Maps legacy codes to new values (e.g. enum key renames). |
mnRelations | MnRelationMapping[] | Many-to-many join table mappings. |
MigrationStep
Each step maps one legacy entity type (e.g. a database table or export file) to a target class.
{
"source": "EMPLOYEES",
"target": "commons.person",
"fields": [...],
"relations": [...]
}
| Property | Type | Description |
|---|---|---|
source | string | Legacy entity identifier (e.g. table name or export filename). |
target | TypeFQN | Target class. |
prefix | string | Optional namespace prefix for disambiguation. |
fields | FieldMapping[] | Field mappings for this entity. |
relations | RelationMapping[] | Relation mappings for this entity. |
FieldMapping
Maps a single field from the legacy entity to a value type on the target class.
{ "source": "FIRST_NAME", "target": "firstName" }
{ "source": "EMP_STATUS", "target": "status", "defaultValue": "active" }
| Property | Type | Description |
|---|---|---|
source | string | Field name in the legacy entity. |
target | string | Target value type field name. |
type | string | Type hint. Use "OBJECT" for nested object fields (handled separately by the migration tool). |
defaultValue | string | Fallback value when the source field is absent or empty. |
key | boolean | When true, this field is used by the migration tool for duplicate detection. |
RelationMapping
Maps a relation field from the legacy entity to a target relation type.
{ "source": "DEPARTMENT_ID", "target": "my-project.department" }
{ "source": "TAG_IDS", "target": "my-project.tag", "multiple": true }
| Property | Type | Description |
|---|---|---|
source | string | Relation field name in the legacy entity. |
target | TypeFQN | Target relation type. |
multiple | boolean | When true, this is a many-to-many relation and the REST endpoint uses the plural form. |
prefix | string | Disambiguation prefix. |
deferred | boolean | When true, the migration tool must resolve this relation in a second pass, after all objects have been created. Default: false. |
Deferred relations
A step creates and links the rows of one legacy entity in whatever order the source data arrives in — there is no ordering guarantee. When a relation points at an object that the same step may not have created yet, resolving it inline fails intermittently. Mark such a relation deferred: true:
{ "source": "PARENT_SHARE_TYPE_ID", "target": "my-project.underlyingShareType", "deferred": true }
Execution contract for the migration tool: resolve and PATCH every deferred relation in a second pass, only after every object across every step has been created — not inline while creating the row, as with an ordinary relation. By that point the target is guaranteed to exist regardless of source-row order. multiple still decides whether the tool PATCHes a single href or an array under the plural REST name.
Use deferred — not mnRelations — for a forward reference on the row itself. mnRelations models a separate legacy join table; a deferred relation is a plain column on the row, mapped like any other relation mapping, differing only in when it is resolved.
MnRelationMapping
Maps a many-to-many join table in the legacy system to a pair of relation endpoints.
{
"source": "EMPLOYEE_PROJECT",
"sourceFrom": "EMPLOYEE_ID",
"targetFrom": "commons.person",
"sourceTo": "PROJECT_ID",
"targetTo": "my-project.project"
}
| Property | Type | Description |
|---|---|---|
source | string | Legacy join table identifier (e.g. table name or export filename), for the migration tool's own use. Optional. |
sourceFrom | string | Foreign key column for the "from" side in the legacy join table. |
targetFrom | TypeFQN | Target "from" side. |
sourceTo | string | Foreign key column for the "to" side in the legacy join table. |
targetTo | TypeFQN | Target "to" side. |
Complete example
{
"class": "my-project.migrationConfig",
"type": "NONE",
"migration": {
"migrationType": "LegacyHR",
"parameters": [
{ "name": "exportPath" }
],
"valueMap": {
"M": "male",
"F": "female",
"PERM": "permanent",
"TEMP": "fixedTerm"
},
"steps": [
{
"source": "persons",
"target": "commons.person",
"fields": [
{ "source": "first_name", "target": "firstName", "key": true },
{ "source": "last_name", "target": "lastName", "key": true },
{ "source": "gender", "target": "gender" },
{ "source": "email", "target": "emailAddress" }
]
},
{
"source": "agreements",
"target": "my-project.employmentAgreement",
"fields": [
{ "source": "job_title", "target": "jobTitle" },
{ "source": "salary", "target": "salary" },
{ "source": "contract_type", "target": "contractType" }
],
"relations": [
{ "source": "employee_id", "target": "commons.person" },
{ "source": "company_id", "target": "commons.company" }
]
}
]
}
}