diff --git a/assembly.py b/assembly.py
index 8eaef04..a3802d5 100644
--- a/assembly.py
+++ b/assembly.py
@@ -273,6 +273,12 @@ class ViewProviderAsmPartGroup(ViewProviderAsmGroup):
     def canDragAndDropObject(self,_obj):
         return True
 
+    def onDelete(self,_vobj,_subs):
+        return False
+
+    def canDelete(self,_obj):
+        return True
+
     def showParts(self):
         vobj = self.ViewObject
         obj = vobj.Object
@@ -1684,6 +1690,9 @@ class ViewProviderAsmConstraint(ViewProviderAsmGroup):
                                     Elements=sel.Elements)
         AsmConstraint.make(typeid,sel,undo=False)
 
+    def canDelete(self,_obj):
+        return True
+
 
 class AsmConstraintGroup(AsmGroup):
     def __init__(self,parent):
@@ -1726,6 +1735,12 @@ class ViewProviderAsmConstraintGroup(ViewProviderAsmGroup):
     def canDropObjects(self):
         return False
 
+    def canDelete(self,_obj):
+        return True
+
+    def onDelete(self,_vobj,_subs):
+        return False
+
 
 class AsmElementGroup(AsmGroup):
     def __init__(self,parent):
@@ -1797,6 +1812,12 @@ class ViewProviderAsmElementGroup(ViewProviderAsmGroup):
                 FreeCADGui.Selection.addSelection(sel.Object,
                         sel.SubElementNames[0]+obj.Name+'.')
 
+    def onDelete(self,_vobj,_subs):
+        return False
+
+    def canDelete(self,_obj):
+        return True
+
 
 class AsmRelationGroup(AsmBase):
     def __init__(self,parent):
@@ -1876,19 +1897,22 @@ class AsmRelationGroup(AsmBase):
             obj.Group = group
             obj.purgeTouched()
 
+        removes = []
         for k,o in relations.items():
             self.relations.pop(k)
             if o.Count:
                 for child in o.Group:
                     if isTypeOf(child,AsmRelation):
-                        child.Document.removeObject(child.Name)
+                        removes.append(child.Name)
             try:
                 # This could fail if the object is already deleted due to
                 # undo/redo
-                o.Document.removeObject(o.Name)
+                removes.append(o.Name)
             except Exception:
                 pass
 
+        Assembly.scheduleDelete(obj.Document,removes)
+
         for o in new:
             o.Proxy.getConstraints()
 
@@ -2014,9 +2038,6 @@ class ViewProviderAsmRelationGroup(ViewProviderAsmBase):
     def canDropObjects(self):
         return False
 
-    def canDelete(self,_obj):
-        return False
-
     def claimChildren(self):
         return self.ViewObject.Object.Group
 
@@ -2087,11 +2108,9 @@ class AsmRelation(AsmBase):
         remove = []
         if obj.Count > count:
             group = obj.Group
-            remove = group[count:]
+            remove = [o.Name for o in group[count:]]
             obj.Group = group[:count]
-            for o in remove:
-                if isTypeOf(o,AsmRelation):
-                    o.Document.removeObject(o.Name)
+            Assembly.scheduleDelete(obj.Document,remove)
             obj.Count = count
             self.getConstraints()
         elif obj.Count < count:
@@ -2209,9 +2228,12 @@ class ViewProviderAsmRelation(ViewProviderAsmBase):
     def canDropObjects(self):
         return False
 
-    def canDelete(self,_obj):
+    def onDelete(self,_vobj,_subs):
         return False
 
+    def canDelete(self,_obj):
+        return True
+
     def claimChildren(self):
         return self.ViewObject.Object.Group
 
@@ -2228,6 +2250,8 @@ class Assembly(AsmGroup):
     _Timer = QtCore.QTimer()
     _PartMap = {} # maps part to assembly
     _PartArrayMap = {} # maps array part to assembly
+    _ScheduleTimer = QtCore.QTimer()
+    _PendingRemove = []
 
     def __init__(self):
         self.parts = set()
@@ -2359,6 +2383,43 @@ class Assembly(AsmGroup):
         if not ret:
             FreeCAD.closeActiveTransaction()
 
+    @classmethod
+    def scheduleDelete(cls,doc,names):
+        if not names:
+            return
+        if not doc.Recomputing:
+            for name in names:
+                try:
+                    doc.removeObject(name)
+                except Exception:
+                    pass
+            return
+        cls._PendingRemove.append((doc,names))
+        if not cls._ScheduleTimer.isSingleShot():
+            cls._ScheduleTimer.setSingleShot(True)
+            cls._ScheduleTimer.timeout.connect(Assembly.onSchedule)
+        if not cls._ScheduleTimer.isActive():
+            cls._ScheduleTimer.start(50)
+
+    @classmethod
+    def onSchedule(cls):
+        pending = []
+        for doc,names in cls._PendingRemove:
+            try:
+                if doc.Recomputing:
+                    pending.append((doc,names))
+                    continue
+                for name in names:
+                    try:
+                        doc.removeObject(name)
+                    except Exception:
+                        pass
+            except Exception:
+                pass
+        cls._PendingRemove = pending
+        if pending:
+            cls._ScheduleTimer.start(50)
+
     def onSolverChanged(self):
         for obj in self.getConstraintGroup().Group:
             # setup==True usually means we are restoring, so try to restore the