Skip to main content
Version: 8.9 (unreleased)

History migration (experimental)

Use the History Data Migrator to copy process instance audit data to Camunda 8.

info

The history migration mode of the Data Migrator will not be released before Camunda 8.9 (April 2026). You can check the current state and track progress in the GitHub repository.

About history migration

Process instances leave traces, referred to as History in Camunda 7. These are audit logs of when a process instance was started, what path it took, and so on.

It is important to note that audit data can exist for ended processes from the past, but is also available for currently still running process instances, as those process instances also left traces up to the current wait state.

The History Data Migrator can copy this audit data to Camunda 8.

Audit data migration might need to look at a huge amount of data, which can take time to migrate. In early measurements, migrating 10,000 process instances took around 10 minutes, but the number varies greatly based on the amount of data attached to a process instance (for example, user task instances, variable instances, and so on).

You can run audit data migration alongside normal operations (for example, after the successful big bang migration of runtime process instances) so that it doesn't require downtime and as such, the performance might not be as critical as for runtime instance migration.

Requirements and limitations

The following requirements and limitations apply:

  • The History Data Migrator must be able to access the Camunda 7 database.

  • The History Data Migrator can migrate data to Camunda 8 only when a relational database (RDBMS) is used. This capability is planned for Camunda 8.9.

  • The History Data Migrator must be able to access the Camunda 8 database. As a result, you can run this tool only in a self-managed environment.

  • If you migrate runtime and history data at the same time, Camunda 8 will contain two process instances:

    • A canceled historic process instance.
    • An active runtime process instance.

    These instances are linked by process variables.

Unsupported entities and properties

The History Data Migrator does not support the following Camunda 8 entities or properties:

  • Sequence flow: Sequence flows cannot be highlighted in Operate.
  • User task migration metadata: Information for user tasks migrated via process instance migration is not available in Camunda 7.
  • Message subscription and correlated message subscription: These entities are not available in Camunda 7.
  • Batch operation entity and batch operation item: Camunda 7 does not retain sufficient information about processed instances.
  • User metrics: Not available in Camunda 7.
  • Exporter position: This entity does not exist in Camunda 7.
  • Process instance and user task tags: These properties do not exist in Camunda 7.
  • Audit log: Not supported. See the related tracking issue.

Usage examples

# Run history migration (experimental)
./start.sh --history

# List all skipped history entities
./start.sh --history --list-skipped

# List skipped entities for specific types
./start.sh --history --list-skipped HISTORY_PROCESS_INSTANCE HISTORY_USER_TASK

# Retry skipped history entities
./start.sh --history --retry-skipped

Entity types

Entity typeDescription
HISTORY_PROCESS_DEFINITIONProcess definitions
HISTORY_PROCESS_INSTANCEProcess instances
HISTORY_INCIDENTProcess incidents
HISTORY_VARIABLEProcess variables
HISTORY_USER_TASKUser tasks
HISTORY_FLOW_NODEFlow node instances
HISTORY_DECISION_INSTANCEDecision instances
HISTORY_DECISION_DEFINITIONDecision definitions

Entity transformation

Entity transformations are handled by built-in interceptors that transform Camunda 7 historic entities into Camunda 8 database models during migration. The History Data Migrator uses the EntityInterceptor interface to allow customization of this conversion process.

Built-in interceptors

The following built-in transformers convert Camunda 7 historic entities:

InterceptorCamunda 7 entity typeCamunda 8 Model
ProcessInstanceTransformerHistoricProcessInstanceProcessInstanceDbModel
ProcessDefinitionTransformerProcessDefinitionProcessDefinitionDbModel
FlowNodeTransformerHistoricActivityInstanceFlowNodeInstanceDbModel
UserTaskTransformerHistoricTaskInstanceUserTaskDbModel
IncidentTransformerHistoricIncidentIncidentDbModel
VariableTransformerHistoricVariableInstanceVariableDbModel
DecisionInstanceTransformerHistoricDecisionInstanceDecisionInstanceDbModel
DecisionDefinitionTransformerHistoricDecisionDefinitionDecisionDefinitionDbModel
DecisionRequirementsDefinitionTransformerHistoricDecisionRequirementsDefinitionDecisionRequirementsDbModel

Disable built-in transformers

You can disable any built-in transformer using the enabled configuration property.

This is useful when your migration use case is more complex and does not work out of the box. In this case, you can migrate entities entirely through custom interceptors:

camunda:
migrator:
# Entity interceptor configuration
interceptors:
- class-name: io.camunda.migration.data.impl.interceptor.history.entity.ProcessInstanceTransformer
enabled: false

Custom transformation

The EntityInterceptor interface allows you to define custom logic that executes when a Camunda 7 historic entity is being converted to a Camunda 8 database model during migration. This is useful for enriching, auditing, or customizing entity conversion.

Custom interceptors are enabled by default and can be restricted to specific entity types.

How to implement an EntityInterceptor

  1. Create a new Maven project with the provided pom.xml structure
  2. Add a dependency on camunda-7-to-8-data-migrator-core (scope: provided)
  3. Implement the EntityInterceptor interface
  4. Add setter methods for any configurable properties
  5. Package as JAR and deploy to the configuration/userlib folder
  6. Configure in configuration/application.yml

Create a custom entity interceptor

Here's an example of a custom entity interceptor which is only called for process instances:

public class ProcessInstanceEnricher implements EntityInterceptor {

/**
* Restrict this interceptor to only handle process instances.
*/
@Override
public Set<Class<?>> getTypes() {
return Set.of(HistoricProcessInstance.class);
}

@Override
public void execute(EntityConversionContext<?, ?> context) {
HistoricProcessInstance c7Instance =
(HistoricProcessInstance) context.getC7Entity();
ProcessInstanceDbModel.Builder c8Builder =
(ProcessInstanceDbModel.Builder) context.getC8DbModelBuilder();

// Custom conversion logic
// For example, add custom metadata or modify the conversion
}
}

Access Camunda 7 process engine

To retrieve information from Camunda 7 entities, use the processEngine available in the EntityConversionContext.

Use it to access services such as RepositoryService and RuntimeService. Fetch additional data as needed from other Camunda 7 entities.

@Override
public void execute(EntityConversionContext<?, ?> context) {
// Use ProcessEngine to retrieve deployment information from Camunda 7 process engine
ProcessEngine processEngine = context.getProcessEngine();

// Example: Retrieve the deployment ID from the process definition
String deploymentId = processEngine.getRepositoryService()
.createProcessDefinitionQuery()
.processDefinitionKey(processInstance.getProcessDefinitionKey())
.singleResult()
.getDeploymentId();
// Custom conversion logic
// ...
}

Limit interceptors by entity type

Entity interceptors can be restricted to specific entity types using the getTypes() method. Use Camunda 7 historic entity classes:

@Override
public Set<Class<?>> getTypes() {
// Handle only specific types
return Set.of(
ProcessDefinition.class, // Process definitions
HistoricProcessInstance.class, // Process instances
HistoricActivityInstance.class, // Flow nodes/activities
HistoricTaskInstance.class, // User tasks
HistoricVariableInstance.class, // Variables
HistoricIncident.class // Incidents
);
}
// Or handle all entity types (default behavior)
@Override
public Set<Class<?>> getTypes() {
return Set.of(); // Empty set = handle all types
}

Configure custom interceptors

Configure your custom interceptors in application.yml:

# Entity interceptor plugins configuration
# These plugins can be packaged in JARs and dropped in the userlib folder
camunda:
migrator:
interceptors:
- class-name: com.example.migrator.ProcessInstanceEnricher
enabled: true
properties:
customProperty: "value"
enableAudit: true

Deployment

  1. Package your custom interceptor as a JAR file
  2. Place the JAR in the configuration/userlib/ folder
  3. Configure the interceptor in configuration/application.yml
  4. Restart the Data Migrator

The enabled property is supported for all interceptors (both built-in and custom) and defaults to true.

See example interceptor.

Execution order

  • Custom interceptors configured in the application.yml are executed in their order of appearance from top to bottom
    • Built-in transformers run first (Order: 1-15), followed by custom interceptors
  • In a Spring Boot environment, you can register interceptors as beans and change their execution order with the @Order annotation (lower values run first)

Error handling

When entity transformation fails:

  1. The migrator skips the entity.
  2. It logs a detailed error message with the entity type and error cause.
  3. It marks the entity as skipped.
  4. Use --history --list-skipped to view skipped entities.
  5. After you fix the underlying issue, use --history --retry-skipped to retry the migration.

History cleanup

The history cleanup date is migrated if the Camunda 7 instance has a removal time.

Tenants

  • Camunda 7's null tenant is migrated to Camunda 8's <default> tenant.
  • All other tenantIds will be migrated as-is.
  • For details, see multi-tenancy in Camunda 8.

Camunda 8 history migration coverage

The following table shows which Camunda 8 entities and properties are migrated by the History Data Migrator.

Audit log

PropertyMigrated
auditLogKeyNo
entityKeyNo
entityTypeNo
operationTypeNo
entityVersionNo
entityValueTypeNo
entityOperationIntentNo
batchOperationKeyNo
batchOperationTypeNo
timestampNo
actorTypeNo
actorIdNo
tenantIdNo
tenantScopeNo
resultNo
annotationNo
categoryNo
processDefinitionIdNo
decisionRequirementsIdNo
decisionDefinitionIdNo
processDefinitionKeyNo
processInstanceKeyNo
elementInstanceKeyNo
jobKeyNo
userTaskKeyNo
decisionRequirementsKeyNo
decisionDefinitionKeyNo
decisionEvaluationKeyNo
deploymentKeyNo
formKeyNo
resourceKeyNo

Batch operation

PropertyMigrated
batchOperationKeyNo
stateNo
operationTypeNo
startDateNo
endDateNo
actorTypeNo
actorIdNo
operationsTotalCountNo
operationsFailedCountNo
operationsCompletedCountNo
errorsNo

Batch operation item

PropertyMigrated
batchOperationKeyNo
itemKeyNo
processInstanceKeyNo
stateNo
processedDateNo
errorMessageNo

Cluster variable

PropertyMigrated
idNo
nameNo
typeNo
doubleValueNo
longValueNo
valueNo
fullValueNo
isPreviewNo
tenantIdNo
scopeNo

Correlated message subscription

PropertyMigrated
correlationKeyNo
correlationTimeNo
flowNodeIdNo
flowNodeInstanceKeyNo
historyCleanupDateNo
messageKeyNo
messageNameNo
partitionIdNo
processDefinitionIdNo
processDefinitionKeyNo
processInstanceKeyNo
rootProcessInstanceKeyNo
subscriptionKeyNo
subscriptionTypeNo
tenantIdNo

Decision definition

PropertyMigrated
decisionDefinitionKeyYes
nameYes
decisionDefinitionIdYes
tenantIdYes
versionYes
decisionRequirementsIdYes
decisionRequirementsKeyYes
decisionRequirementsNameNo
decisionRequirementsVersionNo

Decision instance

PropertyMigrated
decisionInstanceIdNo
decisionInstanceKeyNo
stateYes
evaluationDateYes
evaluationFailureNo
evaluationFailureMessageNo
resultYes
flowNodeInstanceKeyYes
flowNodeIdYes
processInstanceKeyYes
processDefinitionKeyYes
processDefinitionIdYes
decisionDefinitionKeyYes
decisionDefinitionIdYes
decisionRequirementsKeyYes
decisionRequirementsIdYes
rootDecisionDefinitionKeyYes
decisionTypeYes
tenantIdYes
partitionIdYes
evaluatedInputsYes
evaluatedOutputsYes
historyCleanupDateYes

Decision requirements

PropertyMigrated
decisionRequirementsKeyYes
decisionRequirementsIdYes
nameYes
resourceNameYes
versionYes
xmlYes
tenantIdYes

Exporter position

PropertyMigrated
partitionIdNo
exporterNo
lastExportedPositionNo
createdNo
lastUpdatedNo

Flow node instance

PropertyMigrated
flowNodeInstanceKeyNo
processInstanceKeyYes
processDefinitionKeyYes
processDefinitionIdYes
flowNodeScopeKeyYes
startDateYes
endDateYes
flowNodeIdYes
flowNodeNameNo
treePathYes
typeYes
stateYes
incidentKeyNo
numSubprocessIncidentsNo
hasIncidentNo
tenantIdYes
partitionIdNo
rootProcessInstanceKeyNo
historyCleanupDateNo

Form

PropertyMigrated
formKeyNo
tenantIdNo
formIdNo
schemaNo
versionNo
isDeletedNo

History deletion

PropertyMigrated
resourceKeyNo
resourceTypeNo
batchOperationKeyNo
partitionIdNo

Incident

PropertyMigrated
incidentKeyYes
processDefinitionKeyYes
processDefinitionIdYes
processInstanceKeyYes
rootProcessInstanceKeyNo
flowNodeInstanceKeyYes
flowNodeIdYes
jobKeyYes
errorTypeNo
errorMessageYes
errorMessageHashNo
creationDateYes
stateYes
treePathNo
tenantIdYes
partitionIdNo
historyCleanupDateNo

Job

PropertyMigrated
jobKeyNo
typeNo
workerNo
stateNo
kindNo
listenerEventTypeNo
retriesNo
isDeniedNo
deniedReasonNo
hasFailedWithRetriesLeftNo
errorCodeNo
errorMessageNo
serializedCustomHeadersNo
customHeadersNo
deadlineNo
endTimeNo
processDefinitionIdNo
processDefinitionKeyNo
processInstanceKeyNo
rootProcessInstanceKeyNo
elementIdNo
elementInstanceKeyNo
tenantIdNo
partitionIdNo
historyCleanupDateNo
creationTimeNo
lastUpdateTimeNo

Message subscription

PropertyMigrated
messageSubscriptionKeyNo
processDefinitionIdNo
processDefinitionKeyNo
processInstanceKeyNo
rootProcessInstanceKeyNo
flowNodeIdNo
flowNodeInstanceKeyNo
messageSubscriptionStateNo
dateTimeNo
messageNameNo
correlationKeyNo
tenantIdNo
partitionIdNo
historyCleanupDateNo

Process definition

PropertyMigrated
processDefinitionKeyYes
processDefinitionIdYes
resourceNameYes
nameYes
tenantIdYes
versionTagYes
versionYes
bpmnXmlYes
formIdNo

Process instance

PropertyMigrated
processInstanceKeyYes
rootProcessInstanceKeyNo
processDefinitionIdYes
processDefinitionKeyNo
stateYes
startDateYes
endDateYes
tenantIdYes
parentProcessInstanceKeyYes
parentElementInstanceKeyNo
numIncidentsNo
versionYes
partitionIdYes
treePathNo
historyCleanupDateYes
tagsNo

Sequence flow

PropertyMigrated
flowNodeIdNo
processInstanceKeyNo
processDefinitionKeyNo
processDefinitionIdNo
tenantIdNo
partitionIdNo
historyCleanupDateNo

Usage metric

PropertyMigrated
keyNo
startTimeNo
endTimeNo
tenantIdNo
eventTypeNo
valueNo
partitionIdNo

Usage metric (TU)

PropertyMigrated
keyNo
startTimeNo
endTimeNo
tenantIdNo
assigneeHashNo
partitionIdNo

User task

PropertyMigrated
userTaskKeyYes
elementIdYes
nameYes
processDefinitionIdYes
creationDateYes
completionDateYes
assigneeYes
stateYes
formKeyNo
processDefinitionKeyYes
processInstanceKeyYes
rootProcessInstanceKeyNo
elementInstanceKeyYes
tenantIdYes
dueDateYes
followUpDateYes
candidateGroupsNo
candidateUsersNo
externalFormReferenceNo
processDefinitionVersionYes
serializedCustomHeadersNo
customHeadersNo
priorityYes
tagsNo
partitionIdYes
historyCleanupDateYes

User task migration

PropertyMigrated
userTaskKeyNo
processDefinitionKeyNo
processDefinitionIdNo
elementIdNo
nameNo
processDefinitionVersionNo

Variable

PropertyMigrated
variableKeyYes
nameYes
typeNo
doubleValueNo
longValueNo
valueYes
fullValueNo
isPreviewNo
scopeKeyYes
processInstanceKeyYes
rootProcessInstanceKeyNo
processDefinitionIdYes
tenantIdYes
partitionIdYes
historyCleanupDateYes