diff --git a/src/SpecHelper.js b/src/SpecHelper.js
index 079c7627..e2afb847 100644
--- a/src/SpecHelper.js
+++ b/src/SpecHelper.js
@@ -25,7 +25,7 @@ g.g = g
 
 g.YConcurrency_TestingMode = true
 
-jasmine.DEFAULT_TIMEOUT_INTERVAL = 10000
+jasmine.DEFAULT_TIMEOUT_INTERVAL = 20000
 
 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 db880cf6..32a1d30c 100644
--- a/src/Struct.js
+++ b/src/Struct.js
@@ -41,7 +41,8 @@ module.exports = function (Y/* :any */) {
     },
     Insert: {
       /* {
-          content: any,
+          content: [any],
+          opContent: Id,
           id: Id,
           left: Id,
           origin: Id,
@@ -96,13 +97,13 @@ module.exports = function (Y/* :any */) {
           return 0
         } else {
           var d = 0
-          var o = yield* this.getOperation(op.left)
+          var o = yield* this.getInsertion(op.left)
           while (!Y.utils.compareIds(op.origin, (o ? o.id : null))) {
             d++
             if (o.left == null) {
               break
             } else {
-              o = yield* this.getOperation(o.left)
+              o = yield* this.getInsertion(o.left)
             }
           }
           return d
@@ -130,7 +131,7 @@ module.exports = function (Y/* :any */) {
         if (op.origin != null) { // TODO: !== instead of !=
           // we save in origin that op originates in it
           // we need that later when we eventually garbage collect origin (see transaction)
-          var origin = yield* this.getOperation(op.origin)
+          var origin = yield* this.getInsertionCleanEnd(op.origin)
           if (origin.originOf == null) {
             origin.originOf = []
           }
@@ -145,8 +146,8 @@ module.exports = function (Y/* :any */) {
 
         // find o. o is the first conflicting operation
         if (op.left != null) {
-          o = yield* this.getOperation(op.left)
-          o = (o.right == null) ? null : yield* this.getOperation(o.right)
+          o = yield* this.getInsertionCleanEnd(op.left)
+          o = (o.right == null) ? null : yield* this.getInsertionCleanStart(o.right)
         } else { // left == null
           parent = yield* this.getOperation(op.parent)
           let startId = op.parentSub ? parent.map[op.parentSub] : parent.start
@@ -175,7 +176,7 @@ module.exports = function (Y/* :any */) {
             }
             i++
             if (o.right != null) {
-              o = yield* this.getOperation(o.right)
+              o = yield* this.getInsertionCleanStart(o.right)
             } else {
               o = null
             }
@@ -194,15 +195,24 @@ module.exports = function (Y/* :any */) {
         // reconnect left and set right of op
         if (op.left != null) {
           left = yield* this.getOperation(op.left)
-          op.right = left.right
-          left.right = op.id
+          if (false && op.content != null && left.content != null && left.id[0] === op.id[0] && left.id[1] + left.content.length === op.id[1] && left.originOf == null && left.deleted !== true && left.gc !== true) {
+            // extend left
+            left.content = left.content.concat(op.content)
+            op = left
+          } else {
+            // link left
+            op.right = left.right
+            left.right = op.id
 
-          yield* this.setOperation(left)
+            yield* this.setOperation(left)
+          }
         } else {
+          // set op.right from parent, if necessary
           op.right = op.parentSub ? parent.map[op.parentSub] || null : parent.start
         }
         // reconnect right
         if (op.right != null) {
+          // TODO: wanna connect right too?
           right = yield* this.getOperation(op.right)
           right.left = op.id
 
@@ -367,7 +377,7 @@ module.exports = function (Y/* :any */) {
           if (res == null || res.deleted) {
             return void 0
           } else if (res.opContent == null) {
-            return res.content
+            return res.content[0]
           } else {
             return yield* this.getType(res.opContent)
           }
diff --git a/src/Transaction.js b/src/Transaction.js
index 3ac10c24..b0a54eb8 100644
--- a/src/Transaction.js
+++ b/src/Transaction.js
@@ -176,7 +176,7 @@ 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.getOperation(targetId)
+      var target = yield* this.getInsertionCleanStartEnd(targetId)
       var callType = false
 
       if (target == null || !target.deleted) {
@@ -751,11 +751,75 @@ module.exports = function (Y/* :any */) {
         this.store.y.connector.broadcastOps([op])
       }
     }
-    * getOperation (id/* :any */)/* :Transaction<any> */ {
-      var o = yield* this.os.find(id)
-      if (o != null || id[0] !== '_') {
-        return o
+    * getInsertion (id) {
+      var ins = yield* this.os.findWithUpperBound(id)
+      var len = ins.content != null ? ins.content.length : 1 // in case of opContent
+      if (ins != null && id[0] === ins.id[0] && id[1] < ins.id[1] + len) {
+        return ins
       } else {
+        return null
+      }
+    }
+    * getInsertionCleanStartEnd (id) {
+      yield* this.getInsertionCleanStart(id)
+      yield* this.getInsertionCleanEnd(id)
+    }
+    // Return an insertion such that id is the first element of content
+    // This function manipulates an operation, if necessary
+    * getInsertionCleanStart (id) {
+      var ins = yield* this.getInsertion(id)
+      if (ins != null) {
+        if (ins.id[1] === id[1]) {
+          return ins
+        } else {
+          var left = Y.utils.copyObject(ins)
+          ins.content = left.content.splice(ins.id[1] - id[1])
+          ins.id = id
+          ins.origin = left.id
+          left.originOf = [ins.id]
+          left.right = ins.id
+          ins.left = left.id
+          debugger // check
+          yield* this.setOperation(left)
+          yield* this.setOperation(ins)
+          return ins
+        }
+      } else {
+        return null
+      }
+    }
+    // Return an insertion such that id is the last element of content
+    // This function manipulates an operation, if necessary
+    * getInsertionCleanEnd (id) {
+      var ins = yield* this.getInsertion(id)
+      if (ins != null) {
+        if (ins.content == null || (ins.id[1] + ins.content.length - 1 === id[1])) {
+          return ins
+        } else {
+          var right = Y.utils.copyObject(ins)
+          right.content = ins.content.splice(-(ins.id[1] + ins.content.length - 1 - id[1])) // cut off remainder
+          right.id = [id[0], id[1] + 1]
+          right.origin = ins.id
+          ins.originOf = [right.id]
+          ins.right = right.id
+          right.left = ins.id
+          debugger // check
+          yield* this.setOperation(right)
+          yield* this.setOperation(ins)
+          return ins
+        }
+      } else {
+        return null
+      }
+    }
+    * getOperation (id/* :any */)/* :Transaction<any> */ {
+      if (id.length > 2) {
+        id = [id[0], id[1]]
+      }
+      var o = yield* this.os.find(id)
+      if (id[0] !== '_' || o != null) {
+        return o
+      } else { // type is string
         // generate this operation?
         var comp = id[1].split('_')
         if (comp.length > 1) {
@@ -770,7 +834,6 @@ module.exports = function (Y/* :any */) {
           debugger // eslint-disable-line
           return null
         }
-        return null
       }
     }
     * removeOperation (id) {
diff --git a/src/Utils.js b/src/Utils.js
index a45469dd..2f87c4de 100644
--- a/src/Utils.js
+++ b/src/Utils.js
@@ -249,11 +249,14 @@ module.exports = function (Y /* : any*/) {
       }
       return false
     }
-    if (id1[0] === id2[0] && id1[1] === id2[1]) {
-      return true
-    } else {
-      return false
+    if (id1[0] === id2[0]) {
+      var add1 = id1.length > 2 ? id1[2] : 0
+      var add2 = id2.length > 2 ? id2[2] : 0
+      if (id1[1] + add1 === id2[1] + add2) {
+        return true
+      }
     }
+    return false
   }
   Y.utils.compareIds = compareIds
 
@@ -374,13 +377,23 @@ module.exports = function (Y /* : any*/) {
         yield* this.flush()
         yield* super.delete(id)
       }
-      * findWithLowerBound () {
-        yield* this.flush()
-        return yield* super.findWithLowerBound.apply(this, arguments)
+      * findWithLowerBound (id) {
+        var o = yield* this.find(id)
+        if (o != null) {
+          return o
+        } else {
+          yield* this.flush()
+          return yield* super.findWithLowerBound.apply(this, arguments)
+        }
       }
-      * findWithUpperBound () {
-        yield* this.flush()
-        return yield* super.findWithUpperBound.apply(this, arguments)
+      * findWithUpperBound (id) {
+        var o = yield* this.find(id)
+        if (o != null) {
+          return o
+        } else {
+          yield* this.flush()
+          return yield* super.findWithUpperBound.apply(this, arguments)
+        }
       }
       * findNext () {
         yield* this.flush()