diff --git a/src/Database.js b/src/Database.js
index b9998b4eb86f865058ac781ff387d8fdbc3bcf47..768c4493765cbc5fb0173d644c58cfde99d2e155 100644
--- a/src/Database.js
+++ b/src/Database.js
@@ -334,7 +334,8 @@ module.exports = function (Y /* :any */) {
       this.store.addToDebug('yield* this.store.tryExecute.call(this, ', JSON.stringify(op), ')')
       if (op.struct === 'Delete') {
         yield* Y.Struct.Delete.execute.call(this, op)
-        yield* this.store.operationAdded(this, op)
+        // the following is now called in Transaction.deleteOperation!
+        // yield* this.store.operationAdded(this, op)
       } else {
         var defined = yield* this.getOperation(op.id)
         if (defined == null) {
@@ -372,6 +373,7 @@ module.exports = function (Y /* :any */) {
     // called by a transaction when an operation is added
     * operationAdded (transaction, op) {
       if (op.struct === 'Delete') {
+        throw new Error('this section shouldnt be entered anymore!')
         var target = yield* transaction.getOperation(op.target)
         if (target != null) {
           var type = transaction.store.initializedTypes[JSON.stringify(target.parent)]
diff --git a/src/Struct.js b/src/Struct.js
index 12da1534255a994c84447712b232459aab75e921..eafc0d7136cd3390421059e21413c191e44c4951 100644
--- a/src/Struct.js
+++ b/src/Struct.js
@@ -36,7 +36,7 @@ module.exports = function (Y/* :any */) {
         return [] // [op.target]
       },
       execute: function * (op) {
-        return yield* this.deleteOperation(op.target)
+        return yield* this.deleteOperation(op.target, op.length || 1)
       }
     },
     Insert: {
diff --git a/src/Transaction.js b/src/Transaction.js
index b1fe04441804cb8c26cd19df467b116b5749d12a..c7e27b738a4f0e7d42b73507a747810fc8eed1c7 100644
--- a/src/Transaction.js
+++ b/src/Transaction.js
@@ -183,83 +183,102 @@ module.exports = function (Y/* :any */) {
     /*
       Mark an operation as deleted, and add it to the GC, if possible.
     */
-    * deleteOperation (targetId, preventCallType) /* :Generator<any, any, any> */ {
-      var target = yield* this.getInsertionCleanStartEnd(targetId)
-      var callType = false
-
-      if (target == null || !target.deleted) {
-        yield* this.markDeleted(targetId, 1)
+    * deleteOperation (targetId, length) /* :Generator<any, any, any> */ {
+      if (length == null) {
+        length = 1
       }
-
-      if (target != null) {
-        if (!target.deleted) {
-          callType = true
-          // set deleted & notify type
-          target.deleted = true
+      yield* this.markDeleted(targetId, length)
+      while (length > 0) {
+        var callType = false
+        var target = yield* this.os.findWithUpperBound([targetId[0], targetId[1] + length - 1])
+        var targetLength = target != null && target.content != null ? target.content.length : 1
+        if (target == null || target.id[0] !== targetId[0] || target.id[1] + targetLength <= targetId[1]) {
+          // does not exist or is not in the range of the deletion
+          target = null
+          length = 0
+        } else {
+          // does exist, check if it is too long
+          if (target.id[1] < targetId[1]) {
+            // starts to the left of the deletion range
+            target = yield* this.getInsertionCleanStart(targetId)
+            targetLength = target.content.length // must have content property!
+          }
+          if (target.id[1] + targetLength > targetId[1] + length) {
+            // ends to the right of the deletion range
+            target = yield* this.getInsertionCleanEnd([targetId[0], targetId[1] + length - 1])
+            targetLength = target.content.length
+          }
+          length = target.id[1] - targetId[1]
+        }
+  
+        if (target != null) {
+          if (!target.deleted) {
+            callType = true
+            // set deleted & notify type
+            target.deleted = true
+            // delete containing lists
+            if (target.start != null) {
+              // TODO: don't do it like this .. -.-
+              yield* this.deleteList(target.start)
+              // yield* this.deleteList(target.id) -- do not gc itself because this may still get referenced
+            }
+            if (target.map != null) {
+              for (var name in target.map) {
+                yield* this.deleteList(target.map[name])
+              }
+              // TODO: here to..  (see above)
+              // yield* this.deleteList(target.id) -- see above
+            }
+            if (target.opContent != null) {
+              yield* this.deleteOperation(target.opContent)
+              // target.opContent = null
+            }
+            if (target.requires != null) {
+              for (var i = 0; i < target.requires.length; i++) {
+                yield* this.deleteOperation(target.requires[i])
+              }
+            }
+          }
+          var left
+          if (target.left != null) {
+            left = yield* this.getInsertion(target.left)
+          } else {
+            left = null
+          }
+  
+          this.store.addToGarbageCollector(target, left)
+  
+          // set here because it was deleted and/or gc'd
+          yield* this.setOperation(target)
+  
           /*
-          if (!preventCallType) {
+            Check if it is possible to add right to the gc.
+            Because this delete can't be responsible for left being gc'd,
+            we don't have to add left to the gc..
+          */
+          var right
+          if (target.right != null) {
+            right = yield* this.getOperation(target.right)
+          } else {
+            right = null
+          }
+          if (
+            right != null &&
+            this.store.addToGarbageCollector(right, target)
+          ) {
+            yield* this.setOperation(right)
+          }
+          if (callType) {
             var type = this.store.initializedTypes[JSON.stringify(target.parent)]
             if (type != null) {
               yield* type._changed(this, {
                 struct: 'Delete',
-                target: targetId
+                target: target.id,
+                length: targetLength
               })
             }
           }
-          */
-          // delete containing lists
-          if (target.start != null) {
-            // TODO: don't do it like this .. -.-
-            yield* this.deleteList(target.start)
-            // yield* this.deleteList(target.id) -- do not gc itself because this may still get referenced
-          }
-          if (target.map != null) {
-            for (var name in target.map) {
-              yield* this.deleteList(target.map[name])
-            }
-            // TODO: here to..  (see above)
-            // yield* this.deleteList(target.id) -- see above
-          }
-          if (target.opContent != null) {
-            yield* this.deleteOperation(target.opContent)
-            // target.opContent = null
-          }
-          if (target.requires != null) {
-            for (var i = 0; i < target.requires.length; i++) {
-              yield* this.deleteOperation(target.requires[i])
-            }
-          }
-        }
-        var left
-        if (target.left != null) {
-          left = yield* this.getInsertion(target.left)
-        } else {
-          left = null
         }
-
-        this.store.addToGarbageCollector(target, left)
-
-        // set here because it was deleted and/or gc'd
-        yield* this.setOperation(target)
-
-        /*
-          Check if it is possible to add right to the gc.
-          Because this delete can't be responsible for left being gc'd,
-          we don't have to add left to the gc..
-        */
-        var right
-        if (target.right != null) {
-          right = yield* this.getOperation(target.right)
-        } else {
-          right = null
-        }
-        if (
-          right != null &&
-          this.store.addToGarbageCollector(right, target)
-        ) {
-          yield* this.setOperation(right)
-        }
-        return callType
       }
     }
     /*
@@ -470,8 +489,8 @@ module.exports = function (Y/* :any */) {
     */
     * garbageCollectOperation (id) {
       this.store.addToDebug('yield* this.garbageCollectOperation(', id, ')')
-      var o = yield* this.getInsertionCleanStartEnd(id)
-      yield* this.markGarbageCollected(id, 1) // always mark gc'd
+      var o = yield* this.getInsertion(id)  // TODO! like this? or rather cleanstartend
+      yield* this.markGarbageCollected(id, (o != null && o.content != null) ? o.content.lengh : 1) // always mark gc'd
       // if op exists, then clean that mess up..
       if (o != null) {
         /*
@@ -717,11 +736,7 @@ module.exports = function (Y/* :any */) {
         if (del[1] < state.clock) {
           for (let c = del[1]; c < del[1] + del[2]; c++) {
             var id = [del[0], c]
-            var addOperation = yield* this.deleteOperation(id)
-            if (addOperation) {
-              // TODO:.. really .. here? You could prevent calling all these functions in operationAdded
-              yield* this.store.operationAdded(this, {struct: 'Delete', target: id})
-            }
+            yield* this.deleteOperation(id)
             if (del[3]) {
               // gc
               yield* this.garbageCollectOperation(id)