diff --git a/src/structs/ContentDoc.js b/src/structs/ContentDoc.js
index 89233a5b..1b35d785 100644
--- a/src/structs/ContentDoc.js
+++ b/src/structs/ContentDoc.js
@@ -132,4 +132,8 @@ export class ContentDoc {
  * @param {UpdateDecoderV1 | UpdateDecoderV2} decoder
  * @return {ContentDoc}
  */
-export const readContentDoc = decoder => new ContentDoc(new Doc({ guid: decoder.readString(), ...decoder.readAny() }))
+export const readContentDoc = decoder => {
+  const guid = decoder.readString()
+  const opts = decoder.readAny()
+  return new ContentDoc(new Doc({ guid, ...opts, shouldLoad: opts.shouldLoad || opts.autoLoad || false }))
+}
diff --git a/src/utils/Doc.js b/src/utils/Doc.js
index 38226599..2fba3f1d 100644
--- a/src/utils/Doc.js
+++ b/src/utils/Doc.js
@@ -28,6 +28,7 @@ export const generateNewClientId = random.uint32
  * @property {string | null} [DocOpts.collectionid] Associate this document with a collection. This only plays a role if your provider has a concept of collection.
  * @property {any} [DocOpts.meta] Any kind of meta information you want to associate with this document. If this is a subdocument, remote peers will store the meta information as well.
  * @property {boolean} [DocOpts.autoLoad] If a subdocument, automatically load document. If this is a subdocument, remote peers will load the document as well automatically.
+ * @property {boolean} [DocOpts.shouldLoad] Whether the document should be synced by the provider now. This is toggled to true when you call ydoc.load()
  */
 
 /**
@@ -38,7 +39,7 @@ export class Doc extends Observable {
   /**
    * @param {DocOpts} [opts] configuration
    */
-  constructor ({ guid = random.uuidv4(), collectionid = null, gc = true, gcFilter = () => true, meta = null, autoLoad = false } = {}) {
+  constructor ({ guid = random.uuidv4(), collectionid = null, gc = true, gcFilter = () => true, meta = null, autoLoad = false, shouldLoad = true } = {}) {
     super()
     this.gc = gc
     this.gcFilter = gcFilter
@@ -67,7 +68,7 @@ export class Doc extends Observable {
      * @type {Item?}
      */
     this._item = null
-    this.shouldLoad = autoLoad
+    this.shouldLoad = shouldLoad
     this.autoLoad = autoLoad
     this.meta = meta
   }
@@ -252,12 +253,13 @@ export class Doc extends Observable {
         // @ts-ignore
         content.doc = null
       } else {
-        content.doc = new Doc({ guid: this.guid, ...content.opts })
+        content.doc = new Doc({ guid: this.guid, ...content.opts, shouldLoad: false })
         content.doc._item = item
       }
       transact(/** @type {any} */ (item).parent.doc, transaction => {
+        const doc = content.doc
         if (!item.deleted) {
-          transaction.subdocsAdded.add(content.doc)
+          transaction.subdocsAdded.add(doc)
         }
         transaction.subdocsRemoved.add(this)
       }, null, true)
diff --git a/tests/doc.tests.js b/tests/doc.tests.js
index 200f5ba3..63abee87 100644
--- a/tests/doc.tests.js
+++ b/tests/doc.tests.js
@@ -88,7 +88,7 @@ export const testSubdoc = tc => {
     subdocs.get('a').load()
     t.compare(event, [[], [], ['a']])
 
-    subdocs.set('b', new Y.Doc({ guid: 'a' }))
+    subdocs.set('b', new Y.Doc({ guid: 'a', shouldLoad: false }))
     t.compare(event, [['a'], [], []])
     subdocs.get('b').load()
     t.compare(event, [[], [], ['a']])
@@ -124,3 +124,92 @@ export const testSubdoc = tc => {
     t.compare(Array.from(doc2.getSubdocGuids()), ['a', 'c'])
   }
 }
+
+/**
+ * @param {t.TestCase} tc
+ */
+export const testSubdocLoadEdgeCases = tc => {
+  const ydoc = new Y.Doc()
+  const yarray = ydoc.getArray()
+  const subdoc1 = new Y.Doc()
+  /**
+   * @type {any}
+   */
+  let lastEvent = null
+  ydoc.on('subdocs', event => {
+    lastEvent = event
+  })
+  yarray.insert(0, [subdoc1])
+  t.assert(subdoc1.shouldLoad)
+  t.assert(subdoc1.autoLoad === false)
+  t.assert(lastEvent !== null && lastEvent.loaded.has(subdoc1))
+  t.assert(lastEvent !== null && lastEvent.added.has(subdoc1))
+  // destroy and check whether lastEvent adds it again to added (it shouldn't)
+  subdoc1.destroy()
+  const subdoc2 = yarray.get(0)
+  t.assert(subdoc1 !== subdoc2)
+  t.assert(lastEvent !== null && lastEvent.added.has(subdoc2))
+  t.assert(lastEvent !== null && !lastEvent.loaded.has(subdoc2))
+  // load
+  subdoc2.load()
+  t.assert(lastEvent !== null && !lastEvent.added.has(subdoc2))
+  t.assert(lastEvent !== null && lastEvent.loaded.has(subdoc2))
+  // apply from remote
+  const ydoc2 = new Y.Doc()
+  ydoc2.on('subdocs', event => {
+    lastEvent = event
+  })
+  Y.applyUpdate(ydoc2, Y.encodeStateAsUpdate(ydoc))
+  const subdoc3 = ydoc2.getArray().get(0)
+  t.assert(subdoc3.shouldLoad === false)
+  t.assert(subdoc3.autoLoad === false)
+  t.assert(lastEvent !== null && lastEvent.added.has(subdoc3))
+  t.assert(lastEvent !== null && !lastEvent.loaded.has(subdoc3))
+  // load
+  subdoc3.load()
+  t.assert(subdoc3.shouldLoad)
+  t.assert(lastEvent !== null && !lastEvent.added.has(subdoc3))
+  t.assert(lastEvent !== null && lastEvent.loaded.has(subdoc3))
+}
+
+/**
+ * @param {t.TestCase} tc
+ */
+export const testSubdocLoadEdgeCasesAutoload = tc => {
+  const ydoc = new Y.Doc()
+  const yarray = ydoc.getArray()
+  const subdoc1 = new Y.Doc({ autoLoad: true })
+  /**
+   * @type {any}
+   */
+  let lastEvent = null
+  ydoc.on('subdocs', event => {
+    lastEvent = event
+  })
+  yarray.insert(0, [subdoc1])
+  t.assert(subdoc1.shouldLoad)
+  t.assert(subdoc1.autoLoad)
+  t.assert(lastEvent !== null && lastEvent.loaded.has(subdoc1))
+  t.assert(lastEvent !== null && lastEvent.added.has(subdoc1))
+  // destroy and check whether lastEvent adds it again to added (it shouldn't)
+  subdoc1.destroy()
+  const subdoc2 = yarray.get(0)
+  t.assert(subdoc1 !== subdoc2)
+  t.assert(lastEvent !== null && lastEvent.added.has(subdoc2))
+  t.assert(lastEvent !== null && !lastEvent.loaded.has(subdoc2))
+  // load
+  subdoc2.load()
+  t.assert(lastEvent !== null && !lastEvent.added.has(subdoc2))
+  t.assert(lastEvent !== null && lastEvent.loaded.has(subdoc2))
+  // apply from remote
+  const ydoc2 = new Y.Doc()
+  ydoc2.on('subdocs', event => {
+    lastEvent = event
+  })
+  Y.applyUpdate(ydoc2, Y.encodeStateAsUpdate(ydoc))
+  const subdoc3 = ydoc2.getArray().get(0)
+  t.assert(subdoc1.shouldLoad)
+  t.assert(subdoc1.autoLoad)
+  t.assert(lastEvent !== null && lastEvent.added.has(subdoc3))
+  t.assert(lastEvent !== null && lastEvent.loaded.has(subdoc3))
+}