Copado Records Cleanup

Updated 4 months ago by Copado Solutions

Copado creates several records that keep track of Copado's activity or are auxiliary to specific functionalities. Some of these records can be safely removed on a frequent basis using Copado's scheduled jobs or with automated Salesforce processes like workflows, triggers or process builder flows. 

This article goes over deleting records and also provides example code snippets for deleting records that are relevant during a short period of time (e.g. when a user story is Work in Progress) but that can be later deleted without disrupting any Copado functionality.

Deleting Records on a Frequent Basis

  1. Create an Advanced Multi-step Deployment record and add as destination org the org where Copado is installed. Since there won't be any metadata or data deployment, the source org can be any org, so both, the source and destination org, could be the org where Copado is installed. You can name the deployment 'Copado Records Cleanup Deployment'.
    If you’re in Winter'21 onwards, you can use an automation template instead of an Advanced Multi-Step Deployment to execute the cleanup. Add an Apex type step for each of the below code snippets that you would like to add in the cleanup:
  1. If you create an Advanced Multi-step Deployment, add an Apex deployment step for each of the following code snippets that you would like to include in the cleanup:
  • Attachments in Copado are used to store information related to different features. Most of these attachments are created and updated automatically by Copado. Over time, some of these attachments may not be useful anymore, for instance, if you created a snapshot difference a while ago and you are no longer using it. In this case,  you can remove the attachments to clean your org.

delete [SELECT Id,ParentId,Body,Name,OwnerId FROM Attachment WHERE <include your condition> ];
Please note that some attachments are useful. For example, when you resolve a conflict using the Online Conflict Resolution feature, Copado stores this resolution in an attachment in the Git repository and can reuse it in the future if the same type of conflict arises (see Smart Conflict Resolution for more information). So if you decide to delete certain attachments, make sure you are aware of the implications of doing this.
  • Copado Notification records are created whenever the Copado backend sends a notification to the Copado application on Salesforce.

delete [SELECT Id From copado__Copado_Notification__c WHERE CreatedDate < LAST_WEEK ];

  • Old failed Copado Deployment records may have no value and are taking up data storage. If this is your case, since deployment history is in a master-detail with deployment, deleting deployments will also clean up the deployment history.

delete [SELECT Id From copado__Deployment__c WHERE CreatedDate < LAST_N_DAYS:7 AND copado__Status__c != 'Completed Successfully'];

If you need the Deployment records for auditing purposes, feel free to delete just the Deployment history which is created whenever changes happen in any Deployment record (e.g. creating or editing a step, changing the step order):

 delete [SELECT Id From copado__Deployment_History__c WHERE CreatedDate < LAST_90_DAYS AND copado__Deployment__r.copado__Status__c = 'Completed Successfully'];

  • User Story Commit and related Snapshot Commit records are created whenever a commit is done on a user story. Deleting these records won't affect commit history since it remains intact in the Git repository. The User Story Commit object is a junction object, therefore the User Story Commit record is deleted automatically by simply deleting the related Snapshot Commit record:
Set<Id> snapshotCommits = new Set<Id>(); for(copado__User_Story_Commit__c userStoryCommit : [SELECT Id, copado__Snapshot_Commit__c FROM copado__User_Story_Commit__c WHERE copado__User_Story__r.copado__Status__c = 'Completed']) { snapshotCommits.add(userStoryCommit.copado__Snapshot_Commit__c); } delete [SELECT Id FROM copado__Git_Org_Commit__c WHERE Id IN :snapshotCommits];

  • User Story Data Commit records are created whenever you commit data to a user story. If a data commit completes with errors, you can delete this record using the below code snippet:
    delete [SELECT Id From copado__User_Story_Data_Commit__c WHERE copado__Status__c != 'Completed Successfully'];

  • Result records are created to store different job results. Old Result records may not be valuable so you can use the below snippet to clear them:
delete [SELECT Id From copado__Result__c WHERE CreatedDate > LAST_90_DAYS];
The code samples are only recommendations, so you can change or adapt the WHERE conditions however you need.


  • User Story Metadata records are created on user stories to track potential conflicts across multiple user stories. Once the user story has been promoted to all environments these records might  not be  relevant anymore:
delete [SELECT Id FROM copado__User_Story_Metadata__c WHERE copado__User_Story__r.copado__Status__c = 'Completed'];

This code snippet has been added as optional because when you do an Org health check, you need to take into consideration that the User Story Metadata provides highly valuable historical reporting context. In addition, you should have also done back promotions to your Hotfix and Training environments before removing this metadata.
  1. Save the deployment.
  2. Open the Scheduled Jobs tab and create a new record.
    1. Name the scheduled job 'Copado Records Cleanup'.
    2. Click on Copado Look up Webhook and select Execute a Deployment.
    3. In the deployment lookup, select the deployment created in step 1.
    4. Select your user to run the scheduled job and click on Save.
  3. Click on Schedule and select the desired frequency for the cleanup deployment to be executed (e.g. every Friday)

Example: Deleting User Story Related Records After Successful Promotion to Production

  • Id promotionId; Get the promotion record Id from the Trigger implementation. The deletion criteria should include the following:
Promotion__r.Status__c = 'Completed Successfully' AND Promotion__r.Destination_Environment__r.Name = 'Production'

  • Get the list of User Story Ids from the Promoted User Story records to delete the User Story Metadata records related to the Promoted User Stories (the Promoted User Story object is a junction object between the Promotion and the User Stories being promoted):

Set<Id> promotedUserStoryIds = new Set<id>();

for(Promoted_User_Story__c promotedUserStory : [SELECT Id, User_Story__c FROM Promoted_User_Story__c WHERE Promotion__c = :promotionId]) {



delete [SELECT Id FROM User_Story_Metadata__c WHERE User_Story__c IN :promotedUserStoryIds];

  • Delete User Story Commits and their related Snapshot Commit records. The User story Commit is a junction object therefore the User Story Commit is deleted automatically by simply deleting the related Snapshot Commit:

Set<Id> snapshotCommitIds = new Set<Id>();

for(User_Story_Commit__c userStoryCommit : [SELECT Id, Snapshot_Commit__c FROM User_Story_Commit__c WHERE User_Story__c IN :promotedUserStoryIds]) {



delete [SELECT Id FROM Git_Org_Commit__c WHERE Id IN :snapshotCommitIds];

How did we do?