diff --git a/src/Database.js b/src/Database.js
index 768c4493765cbc5fb0173d644c58cfde99d2e155..a2a641fa87ab982945605509d0592105cbf128c4 100644
--- a/src/Database.js
+++ b/src/Database.js
@@ -167,20 +167,28 @@ module.exports = function (Y /* :any */) {
 
       returns true iff op was added to GC
     */
-    addToGarbageCollector (op, left) {
+    * addToGarbageCollector (op, left) {
       if (
         op.gc == null &&
-        op.deleted === true &&
-        this.y.connector.isSynced &&
-        left != null &&
-        left.deleted === true
+        op.deleted === true
       ) {
-        op.gc = true
-        this.gc1.push(op.id)
-        return true
-      } else {
-        return false
+        var gc = false
+        if (left != null && left.deleted === true) {
+          gc = true
+        } else if (op.content != null && op.content.length > 1) {
+          op = yield* this.getInsertionCleanStart([op.id[0], op.id[1] + 1])
+          gc = true
+        }
+        if (gc) {
+          op.gc = true
+          yield* this.setOperation(op)
+          if (this.store.y.connector.isSynced) {
+            this.store.gc1.push(op.id)
+          }
+          return true
+        }
       }
+      return false
     }
     removeFromGarbageCollector (op) {
       function filter (o) {
diff --git a/src/SpecHelper.js b/src/SpecHelper.js
index 3a1ac1c9c4b8a0d4e52f32e62c47c65570f07cc0..3c0ec688a8f96faa4820e9a88e13cb20bc4acd4f 100644
--- a/src/SpecHelper.js
+++ b/src/SpecHelper.js
@@ -25,7 +25,7 @@ g.g = g
 
 g.YConcurrency_TestingMode = true
 
-jasmine.DEFAULT_TIMEOUT_INTERVAL = 50000
+jasmine.DEFAULT_TIMEOUT_INTERVAL = 200000
 
 g.describeManyTimes = function describeManyTimes (times, name, f) {
   for (var i = 0; i < times; i++) {
diff --git a/src/Struct.js b/src/Struct.js
index eafc0d7136cd3390421059e21413c191e44c4951..76868621ed541a316d5caeca1f173b5dc8f38174 100644
--- a/src/Struct.js
+++ b/src/Struct.js
@@ -233,10 +233,10 @@ module.exports = function (Y/* :any */) {
           // is a child of a map struct.
           // Then also make sure that only the most left element is not deleted
           if (op.right != null) {
-            yield* this.deleteOperation(op.right, true)
+            yield* this.deleteOperation(op.right, 1)
           }
           if (op.left != null) {
-            yield* this.deleteOperation(op.id, true)
+            yield* this.deleteOperation(op.id, 1)
           }
         } else {
           if (right == null || left == null) {
diff --git a/src/Transaction.js b/src/Transaction.js
index 2de6a8b1ef92555548d2dbb02cdada3cb458d41e..64585176620506ecb17abc4c38cdaf326b12d943 100644
--- a/src/Transaction.js
+++ b/src/Transaction.js
@@ -167,13 +167,6 @@ module.exports = function (Y/* :any */) {
           }
           if (this.store.y.connector.isSynced) {
             this.store.gc1.push(start.id)
-            for (var i = 0; i < delLength; i++) {
-              if (i === 0) {
-                this.store.gc1.push(start.id)
-              } else {
-                this.store.gc1.push([start.id[0], start.id[1] + i])
-              }
-            }
           }
         }
         start = start.right
@@ -248,8 +241,6 @@ module.exports = function (Y/* :any */) {
             left = null
           }
   
-          this.store.addToGarbageCollector(target, left)
-  
           // set here because it was deleted and/or gc'd
           yield* this.setOperation(target)
   
@@ -264,12 +255,6 @@ module.exports = function (Y/* :any */) {
           } 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) {
@@ -280,6 +265,11 @@ module.exports = function (Y/* :any */) {
               })
             }
           }
+          // need to gc in the end!
+          yield* this.store.addToGarbageCollector.call(this, target, left)
+          if (right != null) {
+            yield* this.store.addToGarbageCollector.call(this, right, target)
+          }
         }
       }
     }
@@ -288,6 +278,7 @@ module.exports = function (Y/* :any */) {
     */
     * markGarbageCollected (id, len) {
       // this.mem.push(["gc", id]);
+      this.store.addToDebug('yield* this.markGarbageCollected(', id, len, ')')
       var n = yield* this.markDeleted(id, len)
       if (n.id[1] < id[1] && !n.gc) {
         // un-extend left
@@ -432,13 +423,7 @@ module.exports = function (Y/* :any */) {
       yield* this.os.iterate(this, null, null, function * (op) {
         var opLength = op.content != null ? op.content.length : 1
         if (op.gc) {
-          for (var i = 0; i < opLength; i++) {
-            if (i === 0) {
-              this.store.gc1.push(op.id)
-            } else {
-              this.store.gc1.push([op.id[0], op.id[1] + i])
-            }
-          }
+          this.store.gc1.push(op.id)
         } else {
           if (op.parent != null) {
             var parentDeleted = yield* this.isDeleted(op.parent)
@@ -463,19 +448,16 @@ module.exports = function (Y/* :any */) {
                 }
               }
               yield* this.setOperation(op)
-              for (var i = 0; i < opLength; i++) {
-                if (i === 0) {
-                  this.store.gc1.push(op.id)
-                } else {
-                  this.store.gc1.push([op.id[0], op.id[1] + i])
-                }
-              }
+              this.store.gc1.push(op.id)
               return
             }
           }
-          if (op.deleted && op.left != null) {
-            var left = yield* this.getInsertion(op.left)
-            this.store.addToGarbageCollector(op, left)
+          if (op.deleted) {
+            var left = null
+            if (op.left != null) {
+              left = yield* this.getInsertion(op.left)
+            }
+            yield* this.store.addToGarbageCollector.call(this, op, left)
           }
         }
       })
@@ -491,17 +473,10 @@ module.exports = function (Y/* :any */) {
     */
     * garbageCollectOperation (id) {
       this.store.addToDebug('yield* this.garbageCollectOperation(', id, ')')
-      var o = yield* this.getOperation(id)  // TODO! like this? or rather cleanstartend
-      yield* this.markGarbageCollected(id, (o != null && o.content != null) ? o.content.lengh : 1) // always mark gc'd
+      var o = yield* this.getOperation(id)
+      yield* this.markGarbageCollected(id, (o != null && o.content != null) ? o.content.length : 1) // always mark gc'd
       // if op exists, then clean that mess up..
       if (o != null) {
-        /*
-        if (!o.deleted) {
-          yield* this.deleteOperation(id)
-          o = yield* this.getOperation(id)
-        }
-        */
-
         var deps = []
         if (o.opContent != null) {
           deps.push(o.opContent)
@@ -736,12 +711,29 @@ module.exports = function (Y/* :any */) {
         // always try to delete..
         var state = yield* this.getState(del[0])
         if (del[1] < state.clock) {
-          for (let c = del[1]; c < del[1] + del[2]; c++) {
-            var id = [del[0], c]
-            yield* this.deleteOperation(id)
-            if (del[3]) {
-              // gc
-              yield* this.garbageCollectOperation(id)
+          yield* this.deleteOperation([del[0], del[1]], del[2])
+          if (del[3]) {
+            // gc..
+            yield* this.markGarbageCollected([del[0], del[1]], del[2]) // always mark gc'd
+            // remove operation..
+            var counter = del[1] + del[2]
+            while (counter >= del[1]) {
+              var o = yield* this.os.findWithUpperBound([del[0], counter - 1])
+              var oLen = o.content != null ? o.content.length : 1
+              if (o.id[0] !== del[0] || del[1] < o.id[1] + oLen) {
+                // not in range
+                break
+              }
+              if (o.id[1] + oLen > del[1] + del[2]) {
+                // overlaps right
+                o = yield* this.getInsertionCleanEnd([del[0], del[1] + del[2] - 1])
+              }
+              if (o.id[1] < del[1]) {
+                // overlaps left
+                o = yield* this.getInsertionCleanStart([del[0], del[1]])
+              }
+              yield* this.garbageCollectOperation(o.id)
+              counter = o.id[1]
             }
           }
         } else {
@@ -844,6 +836,9 @@ module.exports = function (Y/* :any */) {
           // debugger // check
           yield* this.setOperation(left)
           yield* this.setOperation(ins)
+          if (left.gc) {
+            this.store.gc1.push(ins.id)
+          }
           return ins
         }
       } else {
@@ -869,6 +864,9 @@ module.exports = function (Y/* :any */) {
           // debugger // check
           yield* this.setOperation(right)
           yield* this.setOperation(ins)
+          if (ins.gc) {
+            this.store.gc1.push(right.id)
+          }
           return ins
         }
       } else {