diff --git a/gulpfile.js b/gulpfile.js
index e2a17a5c2f8e9075ef36b8fc10f24131f31c9ad0..1047764459a5b8d91dd756e2a5bb444096d8e729 100644
--- a/gulpfile.js
+++ b/gulpfile.js
@@ -63,11 +63,12 @@ var options = minimist(process.argv.slice(2), {
     testfiles: 'src/**/*.js'
   }
 })
+var yfiles = polyfills.concat(['src/y.js', 'src/Connector.js', 'src/OperationStore.js', 'src/Struct.js', 'src/Utils.js',
+    'src/OperationStores/RedBlackTree.js', 'src/Memory.js', 'src/**/*.js'])
 
 var files = {
-  y: polyfills.concat(['src/y.js', 'src/Connector.js', 'src/OperationStore.js', 'src/Struct.js', 'src/Utils.js',
-    'src/OperationStores/RedBlackTree.js', 'src/**/*.js', '!src/**/*.spec.js']),
-  test: polyfills.concat([options.testfiles]),
+  y: yfiles.concat(['!src/**/*.spec.js']),
+  test: yfiles.concat([options.testfiles]),
   build_test: ['build_test/y.js']
 }
 
diff --git a/src/Helper.spec.js b/src/Helper.spec.js
index 3045459d3663fa9bf6f6867fbd09d7db5e19b232..813d8df810b1f37d94b1c9d2af82d7873e7c92fb 100644
--- a/src/Helper.spec.js
+++ b/src/Helper.spec.js
@@ -51,30 +51,63 @@ async function applyRandomTransactions (users, objects, transactions, numberOfTr
 }
 
 async function compareAllUsers(users){//eslint-disable-line
-  var s1, s2
+  var s1, s2, ds1, ds2, allDels1, allDels2
   var db1 = []
   function * t1 () {
     s1 = yield* this.getStateSet()
+    ds1 = yield* this.getDeletionSet()
+    allDels1 = []
+    yield* this.ds.iterate(null, null, function (d) {
+      allDels1.push(d)
+    })
   }
   function * t2 () {
     s2 = yield* this.getStateSet()
+    ds2 = yield* this.getDeletionSet()
+    allDels2 = []
+    yield* this.ds.iterate(null, null, function (d) {
+      allDels2.push(d)
+    })
   }
   await users[0].connector.flushAll()
   for (var uid = 0; uid < users.length; uid++) {
+    var u = users[uid]
+    // compare deleted ops against deleteStore
+    u.db.os.iterate(null, null, function (o) {
+      if (o.deleted === true) {
+        expect(u.db.ds.isDeleted(o.id)).toBeTruthy()
+      }
+    })
+    // compare deleteStore against deleted ops
+    u.db.requestTransaction(function * () {
+      var ds = []
+      u.db.ds.iterate(null, null, function (d) {
+        ds.push(d)
+      })
+      for (var j in ds) {
+        var d = ds[j]
+        for (var i = 0; i < d.len; i++) {
+          var o = yield* this.getOperation([d.id[0], d.id[1] + i])
+          expect(o.deleted).toBeTruthy()
+        }
+      }
+    })
+    // compare allDels tree
+    await wait()
     if (s1 == null) {
-      var u = users[uid]
       u.db.requestTransaction(t1)
       await wait()
       u.db.os.iterate(null, null, function(o){//eslint-disable-line
         db1.push(o)
       })
     } else {
-      var u2 = users[uid]
-      u2.db.requestTransaction(t2)
+      u.db.requestTransaction(t2)
       await wait()
       expect(s1).toEqual(s2)
+      expect(allDels1).toEqual(allDels2) // inner structure
+      expect(ds1).toEqual(ds2) // exported structure
       var count = 0
-      u2.db.os.iterate(null, null, function(o){//eslint-disable-line
+      u.db.os.iterate(null, null, function(o){//eslint-disable-line
         expect(db1[count++]).toEqual(o)
       })
     }
diff --git a/src/OperationStore.js b/src/OperationStore.js
index 2f462eb1cded3515f5f1a2c438efd9118c2a9cf8..3b66e21b2adbb30f5c99a4ad6628146ec4ec16f8 100644
--- a/src/OperationStore.js
+++ b/src/OperationStore.js
@@ -166,6 +166,9 @@ class AbstractOperationStore { // eslint-disable-line no-unused-vars
           yield* Struct[op.struct].execute.call(this, op)
           yield* this.addOperation(op)
           yield* this.store.operationAdded(this, op)
+          if (op.deleted === true) {
+            this.ds.delete(op.id)
+          }
           // find next operation to execute
           op = this.store.waitingOperations.find([op.id[0], state.clock])
           if (op != null) {
diff --git a/src/OperationStores/Memory.js b/src/OperationStores/Memory.js
index 7d66b6d8c9e70b0e28a5abe740651dc533570ab0..4759c90e37a362963531ef81d930c96ee0749627 100644
--- a/src/OperationStores/Memory.js
+++ b/src/OperationStores/Memory.js
@@ -1,4 +1,4 @@
-/* global Struct, RBTree, Y */
+/* global Struct, RBTree, Y, compareIds */
 
 function copyObject (o) {
   var c = {}
@@ -8,9 +8,13 @@ function copyObject (o) {
   return c
 }
 
-class DeletionStore { // eslint-disable-line
-  constructor  () {
-    this.ds = {}
+class DeleteStore extends RBTree { // eslint-disable-line
+  constructor () {
+    super()
+  }
+  isDeleted (id) {
+    var n = this.findNodeWithUpperBound(id)
+    return n !== null && n.val.id[0] === id[0] && id[0] < n.val.id[0] + n.val.len
   }
   delete (id) {
     var n = this.findNodeWithUpperBound(id)
@@ -18,92 +22,97 @@ class DeletionStore { // eslint-disable-line
       if (n.val.id[1] === id[1]) {
         // already deleted
         return
-      } else if (n.val.id[1] + n.val.length === id[1]) {
+      } else if (n.val.id[1] + n.val.len === id[1]) {
         // can extend existing deletion
-        n.val.length++
+        n.val.len++
       } else {
         // cannot extend left
-        n = this.add({id: id, length: 1})
+        n = this.add({id: id, len: 1})
       }
     } else {
       // cannot extend left
-      n = this.add({id: id, length: 1})
+      n = this.add({id: id, len: 1})
     }
+    // can extend right?
     var next = n.next()
-    if compareIds([n.val.id[0], n.val.id[1] + n.val.length], next.val.id) {
-      n.val.length += next.val.length
-      this.delete(next.val.id)
+    if (next !== null && compareIds([n.val.id[0], n.val.id[1] + n.val.len], next.val.id)) {
+      n.val.len = n.val.len + next.val.len
+      super.delete(next.val.id)
     }
   }
   // a DeleteSet (ds) describes all the deleted ops in the OS
   toDeleteSet () {
     var ds = {}
     this.iterate(null, null, function (n) {
-      var user = n.val.id[0]
-      var counter = n.val.id[1]
-      var length = n.val.length
+      var user = n.id[0]
+      var counter = n.id[1]
+      var len = n.len
       var dv = ds[user]
       if (dv === void 0) {
         dv = []
         ds[user] = dv
       }
-      dv.push([counter, length])
+      dv.push([counter, len])
     })
-    // returns a set of deletions that need to be applied in order to get to
-    // the state of the supplied ds
-    getDeletions (ds) {
-      var deletions = []
-      function createDeletions (user, start, length) {
-        for (var c = start; c < start + length; c++) {
-          deletions.push({
-            target: [user, c],
-            struct: 'Delete'
-          })
-        }
+    return ds
+  }
+  // returns a set of deletions that need to be applied in order to get to
+  // the state of the supplied ds
+  getDeletions (ds) {
+    var deletions = []
+    function createDeletions (user, start, len) {
+      for (var c = start; c < start + len; c++) {
+        deletions.push({
+          target: [user, c],
+          struct: 'Delete'
+        })
       }
-      for (var user in ds) {
-        var dv = ds[user]
-        var pos = 0
-        var d = dv[pos]
-        this.iterate([user, 0], [user, Number.MAX_VALUE], function (n) {
-          // cases:
-          // 1. d deletes something to the right of n
-          //  => go to next n (break)
-          // 2. d deletes something to the left of n
-          //  => create deletions
-          //  => reset d accordingly
-          //  *)=> if d doesn't delete anything anymore, go to next d (continue)
-          // 3. not 2) and d deletes something that also n deletes
-          //  => reset d so that it doesn't contain n's deletion
-          //  *)=> if d does not delete anything anymore, go to next d (continue)
-          while (d != null) {
-            var diff // describe the diff of length in 1) and 2)
-            if (n.val.id[1] + n.val.length <= d[0]) {
-              // 1)
-              break
-            } else if (d[0] < n.val.id[1]) {
-              // 2)
-              // delete maximum the length of d
-              // else delete as much as possible
-              diff = Math.min(n.val.id[1]-d[0], d[1])
-              createDeletions(user, d[0], diff)
-            } else {
-              // 3)
-              diff = n.val.id[1] + n.val.length - d[0] // never null (see 1)
-            }
-            if (d[1] <= diff) {
-              // d doesn't delete anything anymore
-              d = dv[++pos]
-            } else {
-              d[0] = d[0] + diff // reset pos
-              d[1] = d[1] - diff // reset length
-            }
+    }
+    for (var user in ds) {
+      var dv = ds[user]
+      var pos = 0
+      var d = dv[pos]
+      this.iterate([user, 0], [user, Number.MAX_VALUE], function (n) {
+        // cases:
+        // 1. d deletes something to the right of n
+        //  => go to next n (break)
+        // 2. d deletes something to the left of n
+        //  => create deletions
+        //  => reset d accordingly
+        //  *)=> if d doesn't delete anything anymore, go to next d (continue)
+        // 3. not 2) and d deletes something that also n deletes
+        //  => reset d so that it doesn't contain n's deletion
+        //  *)=> if d does not delete anything anymore, go to next d (continue)
+        while (d != null) {
+          var diff // describe the diff of length in 1) and 2)
+          if (n.id[1] + n.len <= d[0]) {
+            // 1)
+            break
+          } else if (d[0] < n.id[1]) {
+            // 2)
+            // delete maximum the len of d
+            // else delete as much as possible
+            diff = Math.min(n.id[1] - d[0], d[1])
+            createDeletions(user, d[0], diff)
+          } else {
+            // 3)
+            diff = n.id[1] + n.len - d[0] // never null (see 1)
           }
-        })
+          if (d[1] <= diff) {
+            // d doesn't delete anything anymore
+            d = dv[++pos]
+          } else {
+            d[0] = d[0] + diff // reset pos
+            d[1] = d[1] - diff // reset length
+          }
+        }
+      })
+      for (; pos < dv.len; pos++) {
+        d = dv[pos]
+        createDeletions(user, d[0], d[1])
       }
-      this.iterater()
-
     }
+  }
 }
 
 Y.Memory = (function () { // eslint-disable-line no-unused-vars
@@ -113,6 +122,16 @@ Y.Memory = (function () { // eslint-disable-line no-unused-vars
       super(store)
       this.ss = store.ss
       this.os = store.os
+      this.ds = store.ds
+    }
+    * getDeletionSet (id) {
+      return this.ds.toDeleteSet(id)
+    }
+    * isDeleted (id) {
+      return this.ds.isDeleted(id)
+    }
+    * getDeletions (ds) {
+      return this.ds.getDeletions(ds)
     }
     * setOperation (op) { // eslint-disable-line
       // TODO: you can remove this step! probs..
@@ -209,6 +228,10 @@ Y.Memory = (function () { // eslint-disable-line no-unused-vars
       this.ss = {}
       this.waitingTransactions = []
       this.transactionInProgress = false
+      this.ds = new DeleteStore()
+    }
+    logTable () {
+      this.os.logTable()
     }
     requestTransaction (_makeGen) {
       if (!this.transactionInProgress) {
diff --git a/src/OperationStores/Memory.spec.js b/src/OperationStores/Memory.spec.js
new file mode 100644
index 0000000000000000000000000000000000000000..34ae136068b462ffd9de8c226b88b11c13e8ee9f
--- /dev/null
+++ b/src/OperationStores/Memory.spec.js
@@ -0,0 +1,23 @@
+/* global DeleteStore */
+/* eslint-env browser,jasmine,console */
+
+describe('Memory', function () {
+  describe('DeleteStore', function () {
+    var ds
+    beforeEach(function () {
+      ds = new DeleteStore()
+    })
+    it('Deleted operation is deleted', function () {
+      ds.delete(['u1', 10])
+      expect(ds.isDeleted(['u1', 10])).toBeTruthy()
+      expect(ds.toDeleteSet()).toBeTruthy({'u1': [10, 1]})
+    })
+    it('Deleted operation extends other deleted operation', function () {
+      ds.delete(['u1', 10])
+      ds.delete(['u1', 11])
+      expect(ds.isDeleted(['u1', 10])).toBeTruthy()
+      expect(ds.isDeleted(['u1', 11])).toBeTruthy()
+      expect(ds.toDeleteSet()).toBeTruthy({'u1': [10, 2]})
+    })
+  })
+})
diff --git a/src/OperationStores/RedBlackTree.js b/src/OperationStores/RedBlackTree.js
index 371ed4b1e3c8838869a016f7b29d17397d21e3ef..443eea2b0a82212d86541cd63f175d5981dfab44 100644
--- a/src/OperationStores/RedBlackTree.js
+++ b/src/OperationStores/RedBlackTree.js
@@ -1,4 +1,4 @@
-/* global compareIds */
+/* global compareIds, copyObject */
 function smaller (a, b) {
   return a[0] < b[0] || (a[0] === b[0] && a[1] < b[1])
 }
@@ -192,6 +192,18 @@ class RBTree { // eslint-disable-line no-unused-vars
     }
     return true
   }
+  logTable (from = null, to = null) {
+    var os = []
+    this.iterate(from, to, function (o) {
+      var o_ = copyObject(o)
+      var id = o_.id
+      delete o_.id
+      o_['id[0]'] = id[0]
+      o_['id[1]'] = id[1]
+      os.push(o_)
+    })
+    console.table(os)
+  }
   find (id) {
     return this.findNode(id).val
   }
@@ -382,7 +394,7 @@ class RBTree { // eslint-disable-line no-unused-vars
             p = p.right
           }
         } else {
-          return false
+          return null
         }
       }
       this._fixInsert(node)
@@ -391,6 +403,7 @@ class RBTree { // eslint-disable-line no-unused-vars
     }
     this.length++
     this.root.blacken()
+    return node
   }
   _fixInsert (n) {
     if (n.parent === null) {
diff --git a/src/Struct.js b/src/Struct.js
index 9a78519434af81e1d9659629a501723a4f645022..a21a256f90bbe9fc0385a61a99ae60ae0b635127 100644
--- a/src/Struct.js
+++ b/src/Struct.js
@@ -32,6 +32,7 @@ var Struct = {
       if (!target.deleted) {
         target.deleted = true
         yield* this.setOperation(target)
+        this.ds.delete(target.id)
         var t = this.store.initializedTypes[JSON.stringify(target.parent)]
         if (t != null) {
           yield* t._changed(this, copyObject(op))