diff --git a/packages/binary/tangle/approvers/approvers.go b/packages/binary/tangle/approvers/approvers.go
index f9ba5afef8314566899ee3f1deb688747cb55d9d..adf7af3a099ea1dd50714f2719fe24bf5fc46c49 100644
--- a/packages/binary/tangle/approvers/approvers.go
+++ b/packages/binary/tangle/approvers/approvers.go
@@ -24,7 +24,7 @@ func New(transactionId transaction.Id) *Approvers {
 
 // Get's called when we restore the approvers from storage. The bytes and the content will be unmarshaled by an external
 // caller (the objectStorage factory).
-func FromStorage(id []byte) (result *Approvers) {
+func FromStorage(id []byte) (result objectstorage.StorableObject) {
 	var transactionId transaction.Id
 	copy(transactionId[:], id)
 
@@ -92,6 +92,14 @@ func (approvers *Approvers) Remove(transactionId transaction.Id) (modified bool)
 	return
 }
 
+func (approvers *Approvers) Size() (result int) {
+	approvers.approversMutex.RLock()
+	result = len(approvers.approvers)
+	approvers.approversMutex.RUnlock()
+
+	return
+}
+
 func (approvers *Approvers) GetStorageKey() []byte {
 	transactionId := approvers.GetTransactionId()
 
@@ -107,5 +115,7 @@ func (approvers *Approvers) MarshalBinary() (result []byte, err error) {
 }
 
 func (approvers *Approvers) UnmarshalBinary(data []byte) (err error) {
+	approvers.approvers = make(map[transaction.Id]empty)
+
 	return
 }
diff --git a/packages/binary/tangle/events.go b/packages/binary/tangle/events.go
index 5afba2788ccf9899a2abb86c8ea86f7b696a8e6a..91c7013b0fee1136b8073708cfe1fea27399e4f4 100644
--- a/packages/binary/tangle/events.go
+++ b/packages/binary/tangle/events.go
@@ -1,11 +1,41 @@
 package tangle
 
 import (
+	"github.com/iotaledger/goshimmer/packages/binary/transaction"
+	"github.com/iotaledger/goshimmer/packages/binary/transactionmetadata"
 	"github.com/iotaledger/hive.go/events"
 )
 
-type tangleEvents struct {
-	TransactionSolid    *events.Event
-	TransactionAttached *events.Event
-	Error               *events.Event
+type Events struct {
+	TransactionAttached        *events.Event
+	TransactionSolid           *events.Event
+	TransactionMissing         *events.Event
+	MissingTransactionAttached *events.Event
+	TransactionRemoved         *events.Event
+}
+
+func newEvents() *Events {
+	return &Events{
+		TransactionAttached:        events.NewEvent(cachedTransactionEvent),
+		TransactionSolid:           events.NewEvent(cachedTransactionEvent),
+		TransactionMissing:         events.NewEvent(transactionIdEvent),
+		MissingTransactionAttached: events.NewEvent(transactionIdEvent),
+		TransactionRemoved:         events.NewEvent(transactionIdEvent),
+	}
+}
+
+func transactionIdEvent(handler interface{}, params ...interface{}) {
+	missingTransactionId := params[0].(transaction.Id)
+
+	handler.(func(transaction.Id))(missingTransactionId)
+}
+
+func cachedTransactionEvent(handler interface{}, params ...interface{}) {
+	cachedTransaction := params[0].(*transaction.CachedTransaction)
+	cachedTransactionMetadata := params[1].(*transactionmetadata.CachedTransactionMetadata)
+
+	cachedTransaction.RegisterConsumer()
+	cachedTransactionMetadata.RegisterConsumer()
+
+	handler.(func(*transaction.CachedTransaction, *transactionmetadata.CachedTransactionMetadata))(cachedTransaction, cachedTransactionMetadata)
 }
diff --git a/packages/binary/tangle/missingtransaction/missingtransaction.go b/packages/binary/tangle/missingtransaction/missingtransaction.go
index 783017eb994576e5af21b1a1a022045e0a797a7d..8ab086318dd288612957930da8ac8e2adbca55c4 100644
--- a/packages/binary/tangle/missingtransaction/missingtransaction.go
+++ b/packages/binary/tangle/missingtransaction/missingtransaction.go
@@ -10,31 +10,27 @@ import (
 
 type MissingTransaction struct {
 	objectstorage.StorableObjectFlags
-	storageKey []byte
 
-	id           transaction.Id
-	missingSince time.Time
+	transactionId transaction.Id
+	missingSince  time.Time
 }
 
-func New(id transaction.Id) *MissingTransaction {
+func New(transactionId transaction.Id) *MissingTransaction {
 	return &MissingTransaction{
-		storageKey:   id[:],
-		id:           id,
-		missingSince: time.Now(),
+		transactionId: transactionId,
+		missingSince:  time.Now(),
 	}
 }
 
 func FromStorage(key []byte) objectstorage.StorableObject {
-	result := &MissingTransaction{
-		storageKey: make([]byte, len(key)),
-	}
-	copy(result.storageKey, key)
+	result := &MissingTransaction{}
+	copy(result.transactionId[:], key)
 
 	return result
 }
 
-func (missingTransaction *MissingTransaction) GetId() transaction.Id {
-	return missingTransaction.id
+func (missingTransaction *MissingTransaction) GetTransactionId() transaction.Id {
+	return missingTransaction.transactionId
 }
 
 func (missingTransaction *MissingTransaction) GetMissingSince() time.Time {
@@ -42,7 +38,7 @@ func (missingTransaction *MissingTransaction) GetMissingSince() time.Time {
 }
 
 func (missingTransaction *MissingTransaction) GetStorageKey() []byte {
-	return missingTransaction.storageKey
+	return missingTransaction.transactionId[:]
 }
 
 func (missingTransaction *MissingTransaction) Update(other objectstorage.StorableObject) {
@@ -54,7 +50,5 @@ func (missingTransaction *MissingTransaction) MarshalBinary() (result []byte, er
 }
 
 func (missingTransaction *MissingTransaction) UnmarshalBinary(data []byte) (err error) {
-	copy(missingTransaction.id[:], missingTransaction.storageKey)
-
 	return missingTransaction.missingSince.UnmarshalBinary(data)
 }
diff --git a/packages/binary/tangle/tangle.go b/packages/binary/tangle/tangle.go
index a8dd7e60f11b83522aaee6691a5dffa5f8fa2d08..ecf60caa9fa673b055a05590685532b920115400 100644
--- a/packages/binary/tangle/tangle.go
+++ b/packages/binary/tangle/tangle.go
@@ -2,7 +2,7 @@ package tangle
 
 import (
 	"container/list"
-	"fmt"
+	"time"
 
 	"github.com/iotaledger/goshimmer/packages/binary/tangle/approvers"
 	"github.com/iotaledger/goshimmer/packages/binary/tangle/missingtransaction"
@@ -10,52 +10,36 @@ import (
 	"github.com/iotaledger/goshimmer/packages/binary/transactionmetadata"
 	"github.com/iotaledger/goshimmer/packages/storageprefix"
 	"github.com/iotaledger/hive.go/async"
-	"github.com/iotaledger/hive.go/events"
 	"github.com/iotaledger/hive.go/objectstorage"
 )
 
+const (
+	MAX_MISSING_TIME_BEFORE_CLEANUP = 30 * time.Second
+	MISSING_CHECK_INTERVAL          = 5 * time.Second
+)
+
 type Tangle struct {
 	transactionStorage         *objectstorage.ObjectStorage
 	transactionMetadataStorage *objectstorage.ObjectStorage
 	approversStorage           *objectstorage.ObjectStorage
 	missingTransactionsStorage *objectstorage.ObjectStorage
 
-	Events tangleEvents
+	Events Events
 
 	storeTransactionsWorkerPool async.WorkerPool
 	solidifierWorkerPool        async.WorkerPool
+	cleanupWorkerPool           async.WorkerPool
 }
 
+// Constructor for the tangle.
 func New(storageId []byte) (result *Tangle) {
 	result = &Tangle{
-		transactionStorage:         objectstorage.New(append(storageId, storageprefix.TangleTransaction...), transactionFactory),
-		transactionMetadataStorage: objectstorage.New(append(storageId, storageprefix.TangleTransactionMetadata...), transactionFactory),
-		approversStorage:           objectstorage.New(append(storageId, storageprefix.TangleApprovers...), approversFactory),
-		missingTransactionsStorage: objectstorage.New(append(storageId, storageprefix.TangleTransaction...), missingtransaction.FromStorage),
-
-		Events: tangleEvents{
-			TransactionAttached: events.NewEvent(func(handler interface{}, params ...interface{}) {
-				cachedTransaction := params[0].(*transaction.CachedTransaction)
-				cachedTransactionMetadata := params[1].(*transactionmetadata.CachedTransactionMetadata)
-
-				cachedTransaction.RegisterConsumer()
-				cachedTransactionMetadata.RegisterConsumer()
-
-				handler.(func(*transaction.CachedTransaction, *transactionmetadata.CachedTransactionMetadata))(cachedTransaction, cachedTransactionMetadata)
-			}),
-			TransactionSolid: events.NewEvent(func(handler interface{}, params ...interface{}) {
-				cachedTransaction := params[0].(*transaction.CachedTransaction)
-				cachedTransactionMetadata := params[1].(*transactionmetadata.CachedTransactionMetadata)
-
-				cachedTransaction.RegisterConsumer()
-				cachedTransactionMetadata.RegisterConsumer()
-
-				handler.(func(*transaction.CachedTransaction, *transactionmetadata.CachedTransactionMetadata))(cachedTransaction, cachedTransactionMetadata)
-			}),
-			Error: events.NewEvent(func(handler interface{}, params ...interface{}) {
-				handler.(func(error))(params[0].(error))
-			}),
-		},
+		transactionStorage:         objectstorage.New(append(storageId, storageprefix.TangleTransaction...), transaction.FromStorage),
+		transactionMetadataStorage: objectstorage.New(append(storageId, storageprefix.TangleTransactionMetadata...), transactionmetadata.FromStorage),
+		approversStorage:           objectstorage.New(append(storageId, storageprefix.TangleApprovers...), approvers.FromStorage),
+		missingTransactionsStorage: objectstorage.New(append(storageId, storageprefix.TangleMissingTransaction...), missingtransaction.FromStorage),
+
+		Events: *newEvents(),
 	}
 
 	result.solidifierWorkerPool.Tune(1024)
@@ -63,76 +47,183 @@ func New(storageId []byte) (result *Tangle) {
 	return
 }
 
-func (tangle *Tangle) Prune() error {
-	if err := tangle.transactionStorage.Prune(); err != nil {
-		return err
-	}
+// Attaches a new transaction to the tangle.
+func (tangle *Tangle) AttachTransaction(transaction *transaction.Transaction) {
+	tangle.storeTransactionsWorkerPool.Submit(func() { tangle.storeTransactionWorker(transaction) })
+}
 
-	if err := tangle.transactionMetadataStorage.Prune(); err != nil {
-		return err
-	}
+// Triggers the solidification of a given transaction.
+func (tangle *Tangle) SolidifyTransaction(transactionId transaction.Id) {
+	tangle.solidifierWorkerPool.Submit(func() {
+		tangle.solidifyTransactionWorker(tangle.GetTransaction(transactionId), tangle.GetTransactionMetadata(transactionId))
+	})
+}
 
-	if err := tangle.approversStorage.Prune(); err != nil {
-		return err
-	}
+// Deletes a transaction from the tangle (i.e. for local snapshots)
+func (tangle *Tangle) DeleteTransaction(transactionId transaction.Id) {
+	tangle.GetTransaction(transactionId).Consume(func(object objectstorage.StorableObject) {
+		currentTransaction := object.(*transaction.Transaction)
+
+		tangle.GetApprovers(currentTransaction.GetTrunkTransactionId()).Consume(func(object objectstorage.StorableObject) {
+			if _tmp := object.(*approvers.Approvers); _tmp.Remove(transactionId) && _tmp.Size() == 0 {
+				_tmp.Delete()
+			}
+		})
+
+		tangle.GetApprovers(currentTransaction.GetTrunkTransactionId()).Consume(func(object objectstorage.StorableObject) {
+			if _tmp := object.(*approvers.Approvers); _tmp.Remove(transactionId) && _tmp.Size() == 0 {
+				_tmp.Delete()
+			}
+		})
+	})
 
-	return nil
-}
+	tangle.transactionStorage.Delete(transactionId[:])
+	tangle.transactionMetadataStorage.Delete(transactionId[:])
+	tangle.missingTransactionsStorage.Delete(transactionId[:])
 
-func (tangle *Tangle) AttachTransaction(transaction *transaction.Transaction) {
-	tangle.storeTransactionsWorkerPool.Submit(func() { tangle.storeTransaction(transaction) })
+	tangle.Events.TransactionRemoved.Trigger(transactionId)
 }
 
+// Retrieves a transaction from the tangle.
 func (tangle *Tangle) GetTransaction(transactionId transaction.Id) *transaction.CachedTransaction {
 	return &transaction.CachedTransaction{CachedObject: tangle.transactionStorage.Load(transactionId[:])}
 }
 
+// Retrieves the metadata of a transaction from the tangle.
 func (tangle *Tangle) GetTransactionMetadata(transactionId transaction.Id) *transactionmetadata.CachedTransactionMetadata {
 	return &transactionmetadata.CachedTransactionMetadata{CachedObject: tangle.transactionMetadataStorage.Load(transactionId[:])}
 }
 
+// Retrieves the approvers of a transaction from the tangle.
 func (tangle *Tangle) GetApprovers(transactionId transaction.Id) *approvers.CachedApprovers {
 	return &approvers.CachedApprovers{CachedObject: tangle.approversStorage.Load(transactionId[:])}
 }
 
-// Marks the tangle as stopped, so it will not accept any new transactions, and then waits for all backgroundTasks to
-// finish.
+// Marks the tangle as stopped, so it will not accept any new transactions (waits for all backgroundTasks to finish.
 func (tangle *Tangle) Shutdown() *Tangle {
 	tangle.storeTransactionsWorkerPool.ShutdownGracefully()
 	tangle.solidifierWorkerPool.ShutdownGracefully()
+	tangle.cleanupWorkerPool.ShutdownGracefully()
 
 	return tangle
 }
 
-func (tangle *Tangle) storeTransaction(tx *transaction.Transaction) {
-	cachedTransaction, transactionIsNew := tangle.transactionStorage.StoreIfAbsent(tx.GetStorageKey(), tx)
-	if !transactionIsNew {
-		return
+// Resets the database and deletes all objects (good for testing or "node resets").
+func (tangle *Tangle) Prune() error {
+	for _, storage := range []*objectstorage.ObjectStorage{
+		tangle.transactionStorage,
+		tangle.transactionMetadataStorage,
+		tangle.approversStorage,
+		tangle.missingTransactionsStorage,
+	} {
+		if err := storage.Prune(); err != nil {
+			return err
+		}
 	}
 
-	cachedTransactionMetadata := tangle.createTransactionMetadata(tx)
-	tangle.addTransactionToApprovers(tx, tx.GetTrunkTransactionId())
-	tangle.addTransactionToApprovers(tx, tx.GetBranchTransactionId())
+	return nil
+}
+
+// Worker that stores the transactions and calls the corresponding "Storage events"
+func (tangle *Tangle) storeTransactionWorker(tx *transaction.Transaction) {
+	addTransactionToApprovers := func(transactionId transaction.Id, approvedTransactionId transaction.Id) {
+		cachedApprovers := tangle.approversStorage.ComputeIfAbsent(approvedTransactionId[:], func([]byte) objectstorage.StorableObject {
+			result := approvers.New(approvedTransactionId)
+
+			result.SetModified()
+
+			return result
+		})
+
+		if _tmp := cachedApprovers.Get(); _tmp != nil {
+			if approversObject := _tmp.(*approvers.Approvers); approversObject != nil {
+				approversObject.Add(transactionId)
+
+				// if the approvers got "cleaned up" while being in cache, we make sure the object gets persisted again
+				approversObject.Persist()
+			}
+		}
+
+		cachedApprovers.Release()
+	}
+
+	var cachedTransaction *transaction.CachedTransaction
+	if _tmp, transactionIsNew := tangle.transactionStorage.StoreIfAbsent(tx.GetStorageKey(), tx); !transactionIsNew {
+		return
+	} else {
+		cachedTransaction = &transaction.CachedTransaction{CachedObject: _tmp}
+	}
 
 	transactionId := tx.GetId()
+
+	cachedTransactionMetadata := &transactionmetadata.CachedTransactionMetadata{CachedObject: tangle.transactionMetadataStorage.Store(transactionmetadata.New(tx.GetId()))}
+	addTransactionToApprovers(transactionId, tx.GetTrunkTransactionId())
+	addTransactionToApprovers(transactionId, tx.GetBranchTransactionId())
+
 	if tangle.missingTransactionsStorage.DeleteIfPresent(transactionId[:]) {
-		fmt.Println("MISSING TRANSACTION RECEIVED")
+		tangle.Events.MissingTransactionAttached.Trigger(transactionId)
 	}
 
-	tangle.solidifierWorkerPool.Submit(func() {
-		tangle.solidify(&transaction.CachedTransaction{CachedObject: cachedTransaction}, cachedTransactionMetadata)
-	})
-}
+	tangle.Events.TransactionAttached.Trigger(cachedTransaction, cachedTransactionMetadata)
 
-// Payloads can have different solidification rules and it might happen, that an external process needs to "manually
-// trigger" the solidification checks of a transaction (to update it's solidification status).
-func (tangle *Tangle) Solidify(transactionId transaction.Id) {
 	tangle.solidifierWorkerPool.Submit(func() {
-		tangle.solidify(tangle.GetTransaction(transactionId), tangle.GetTransactionMetadata(transactionId))
+		tangle.solidifyTransactionWorker(cachedTransaction, cachedTransactionMetadata)
 	})
 }
 
-func (tangle *Tangle) solidify(cachedTransaction *transaction.CachedTransaction, cachedTransactionMetadata *transactionmetadata.CachedTransactionMetadata) {
+// Worker that solidifies the transactions (recursively from past to present).
+func (tangle *Tangle) solidifyTransactionWorker(cachedTransaction *transaction.CachedTransaction, cachedTransactionMetadata *transactionmetadata.CachedTransactionMetadata) {
+	isTransactionMarkedAsSolid := func(transactionId transaction.Id) bool {
+		if transactionId == transaction.EmptyId {
+			return true
+		}
+
+		transactionMetadataCached := tangle.GetTransactionMetadata(transactionId)
+		if transactionMetadata := transactionMetadataCached.Unwrap(); transactionMetadata == nil {
+			transactionMetadataCached.Release()
+
+			// if transaction is missing and was not reported as missing, yet
+			if cachedMissingTransaction, missingTransactionStored := tangle.missingTransactionsStorage.StoreIfAbsent(transactionId[:], missingtransaction.New(transactionId)); missingTransactionStored {
+				cachedMissingTransaction.Consume(func(object objectstorage.StorableObject) {
+					tangle.monitorMissingTransactionWorker(object.(*missingtransaction.MissingTransaction).GetTransactionId())
+				})
+			}
+
+			return false
+		} else if !transactionMetadata.IsSolid() {
+			transactionMetadataCached.Release()
+
+			return false
+		}
+		transactionMetadataCached.Release()
+
+		return true
+	}
+
+	isTransactionSolid := func(transaction *transaction.Transaction, transactionMetadata *transactionmetadata.TransactionMetadata) bool {
+		if transaction == nil || transaction.IsDeleted() {
+			return false
+		}
+
+		if transactionMetadata == nil || transactionMetadata.IsDeleted() {
+			return false
+		}
+
+		if transactionMetadata.IsSolid() {
+			return true
+		}
+
+		// 1. check tangle solidity
+		isTrunkSolid := isTransactionMarkedAsSolid(transaction.GetTrunkTransactionId())
+		isBranchSolid := isTransactionMarkedAsSolid(transaction.GetBranchTransactionId())
+		if isTrunkSolid && isBranchSolid {
+			// 2. check payload solidity
+			return true
+		}
+
+		return false
+	}
+
 	popElementsFromStack := func(stack *list.List) (*transaction.CachedTransaction, *transactionmetadata.CachedTransactionMetadata) {
 		currentSolidificationEntry := stack.Front()
 		currentCachedTransaction := currentSolidificationEntry.Value.([2]interface{})[0]
@@ -160,7 +251,7 @@ func (tangle *Tangle) solidify(cachedTransaction *transaction.CachedTransaction,
 		}
 
 		// if current transaction is solid and was not marked as solid before: mark as solid and propagate
-		if tangle.isTransactionSolid(currentTransaction, currentTransactionMetadata) && currentTransactionMetadata.SetSolid(true) {
+		if isTransactionSolid(currentTransaction, currentTransactionMetadata) && currentTransactionMetadata.SetSolid(true) {
 			tangle.Events.TransactionSolid.Trigger(currentCachedTransaction, currentCachedTransactionMetadata)
 
 			tangle.GetApprovers(currentTransaction.GetId()).Consume(func(object objectstorage.StorableObject) {
@@ -179,74 +270,45 @@ func (tangle *Tangle) solidify(cachedTransaction *transaction.CachedTransaction,
 	}
 }
 
-func (tangle *Tangle) isTransactionSolid(transaction *transaction.Transaction, transactionMetadata *transactionmetadata.TransactionMetadata) bool {
-	if transaction == nil || transaction.IsDeleted() {
-		return false
-	}
-
-	if transactionMetadata == nil || transactionMetadata.IsDeleted() {
-		return false
-	}
+// Worker that Monitors the missing transactions (by scheduling regular checks).
+func (tangle *Tangle) monitorMissingTransactionWorker(transactionId transaction.Id) {
+	var scheduleNextMissingCheck func(transactionId transaction.Id)
+	scheduleNextMissingCheck = func(transactionId transaction.Id) {
+		time.AfterFunc(MISSING_CHECK_INTERVAL, func() {
+			tangle.missingTransactionsStorage.Load(transactionId[:]).Consume(func(object objectstorage.StorableObject) {
+				missingTransaction := object.(*missingtransaction.MissingTransaction)
 
-	if transactionMetadata.IsSolid() {
-		return true
-	}
+				if time.Since(missingTransaction.GetMissingSince()) >= MAX_MISSING_TIME_BEFORE_CLEANUP {
+					tangle.cleanupWorkerPool.Submit(func() { tangle.cleanupWorker(missingTransaction.GetTransactionId()) })
+				} else {
+					tangle.Events.TransactionMissing.Trigger(transactionId)
 
-	// 1. check tangle solidity
-	isTrunkSolid := tangle.isTransactionMarkedAsSolid(transaction.GetTrunkTransactionId())
-	isBranchSolid := tangle.isTransactionMarkedAsSolid(transaction.GetBranchTransactionId())
-	if isTrunkSolid && isBranchSolid {
-		// 2. check payload solidity
-		return true
+					scheduleNextMissingCheck(transactionId)
+				}
+			})
+		})
 	}
+	tangle.Events.TransactionMissing.Trigger(transactionId)
 
-	return false
+	scheduleNextMissingCheck(transactionId)
 }
 
-func (tangle *Tangle) isTransactionMarkedAsSolid(transactionId transaction.Id) bool {
-	if transactionId == transaction.EmptyId {
-		return true
-	}
+// Worker that recursively cleans up the approvers of a unsolidifiable missing transaction.
+func (tangle *Tangle) cleanupWorker(transactionId transaction.Id) {
+	cleanupStack := list.New()
+	cleanupStack.PushBack(transactionId)
 
-	cachedTransactionMetadata := tangle.GetTransactionMetadata(transactionId)
-	if transactionMetadata := cachedTransactionMetadata.Unwrap(); transactionMetadata == nil {
-		cachedTransactionMetadata.Release()
+	for cleanupStack.Len() >= 1 {
+		currentStackEntry := cleanupStack.Front()
+		currentTransactionId := currentStackEntry.Value.(transaction.Id)
+		cleanupStack.Remove(currentStackEntry)
 
-		if _, missingTransactionStored := tangle.missingTransactionsStorage.StoreIfAbsent(transactionId[:], &missingtransaction.MissingTransaction{}); missingTransactionStored {
-			// Trigger
-			fmt.Println("MISSING TX EVENT")
-		}
-		// transaction is missing -> add to solidifier
-
-		return false
-	} else if !transactionMetadata.IsSolid() {
-		cachedTransactionMetadata.Release()
+		tangle.GetApprovers(currentTransactionId).Consume(func(object objectstorage.StorableObject) {
+			for approverTransactionId := range object.(*approvers.Approvers).Get() {
+				tangle.DeleteTransaction(currentTransactionId)
 
-		return false
+				cleanupStack.PushBack(approverTransactionId)
+			}
+		})
 	}
-	cachedTransactionMetadata.Release()
-
-	return true
-}
-
-func (tangle *Tangle) createTransactionMetadata(transaction *transaction.Transaction) *transactionmetadata.CachedTransactionMetadata {
-	transactionMetadata := transactionmetadata.New(transaction.GetId())
-
-	return &transactionmetadata.CachedTransactionMetadata{CachedObject: tangle.transactionMetadataStorage.Store(transactionMetadata)}
-}
-
-func (tangle *Tangle) addTransactionToApprovers(transaction *transaction.Transaction, trunkTransactionId transaction.Id) {
-	tangle.approversStorage.ComputeIfAbsent(trunkTransactionId[:], func([]byte) objectstorage.StorableObject {
-		return approvers.New(trunkTransactionId)
-	}).Consume(func(object objectstorage.StorableObject) {
-		object.(*approvers.Approvers).Add(transaction.GetId())
-	})
-}
-
-func transactionFactory(key []byte) objectstorage.StorableObject {
-	return transaction.FromStorage(key)
-}
-
-func approversFactory(key []byte) objectstorage.StorableObject {
-	return approvers.FromStorage(key)
 }
diff --git a/packages/binary/tangle/tangle_test.go b/packages/binary/tangle/tangle_test.go
index 71dc0198fc08500415c2d1d92650fbb850228ade..bdeeaa40fc87c436574605cc71e573edab6b9078 100644
--- a/packages/binary/tangle/tangle_test.go
+++ b/packages/binary/tangle/tangle_test.go
@@ -5,6 +5,8 @@ import (
 	"testing"
 	"time"
 
+	"github.com/iotaledger/hive.go/events"
+
 	"github.com/iotaledger/goshimmer/packages/binary/identity"
 	"github.com/iotaledger/goshimmer/packages/binary/transaction"
 	"github.com/iotaledger/goshimmer/packages/binary/transaction/payload/data"
@@ -20,21 +22,16 @@ func BenchmarkTangle_AttachTransaction(b *testing.B) {
 
 	testIdentity := identity.Generate()
 
-	transactionBytes := make([][]byte, b.N)
+	transactionBytes := make([]*transaction.Transaction, b.N)
 	for i := 0; i < b.N; i++ {
-		transactionBytes[i] = transaction.New(transaction.EmptyId, transaction.EmptyId, testIdentity, data.New([]byte("some data"))).GetBytes()
+		transactionBytes[i] = transaction.New(transaction.EmptyId, transaction.EmptyId, testIdentity, data.New([]byte("some data")))
+		transactionBytes[i].GetBytes()
 	}
 
 	b.ResetTimer()
 
 	for i := 0; i < b.N; i++ {
-		if txToAttach, err := transaction.FromBytes(transactionBytes[i]); err != nil {
-			b.Error(err)
-
-			return
-		} else {
-			tangle.AttachTransaction(txToAttach)
-		}
+		tangle.AttachTransaction(transactionBytes[i])
 	}
 
 	tangle.Shutdown()
@@ -48,13 +45,21 @@ func TestTangle_AttachTransaction(t *testing.T) {
 		return
 	}
 
+	tangle.Events.TransactionMissing.Attach(events.NewClosure(func(transactionId transaction.Id) {
+		fmt.Println("MISSING:", transactionId)
+	}))
+
+	tangle.Events.TransactionRemoved.Attach(events.NewClosure(func(transactionId transaction.Id) {
+		fmt.Println("REMOVED:", transactionId)
+	}))
+
 	newTransaction1 := transaction.New(transaction.EmptyId, transaction.EmptyId, identity.Generate(), data.New([]byte("some data")))
 	newTransaction2 := transaction.New(newTransaction1.GetId(), newTransaction1.GetId(), identity.Generate(), data.New([]byte("some other data")))
 
 	fmt.Println("ATTACH", newTransaction2.GetId())
 	tangle.AttachTransaction(newTransaction2)
 
-	time.Sleep(1 * time.Second)
+	time.Sleep(37 * time.Second)
 
 	fmt.Println("ATTACH", newTransaction1.GetId())
 	tangle.AttachTransaction(newTransaction1)
diff --git a/packages/binary/transaction/transaction.go b/packages/binary/transaction/transaction.go
index 6ad2526587b724bfa25147758f80312fbbe22acf..4ec441045a3151ce806ef021668da5239df8b03a 100644
--- a/packages/binary/transaction/transaction.go
+++ b/packages/binary/transaction/transaction.go
@@ -48,7 +48,7 @@ func New(trunkTransactionId Id, branchTransactionId Id, issuer *identity.Identit
 
 // Get's called when we restore a transaction from storage. The bytes and the content will be unmarshaled by an external
 // caller (the objectStorage factory).
-func FromStorage(id []byte) (result *Transaction) {
+func FromStorage(id []byte) (result objectstorage.StorableObject) {
 	var transactionId Id
 	copy(transactionId[:], id)
 
diff --git a/packages/binary/transactionmetadata/transactionmetadata.go b/packages/binary/transactionmetadata/transactionmetadata.go
index f79599e4221a5973721d0fc5e5ddb76e072d63b7..5ef63dbea00e4e73e88abe144faf891faa6f3489 100644
--- a/packages/binary/transactionmetadata/transactionmetadata.go
+++ b/packages/binary/transactionmetadata/transactionmetadata.go
@@ -26,6 +26,13 @@ func New(transactionId transaction.Id) *TransactionMetadata {
 	}
 }
 
+func FromStorage(id []byte) objectstorage.StorableObject {
+	result := &TransactionMetadata{}
+	copy(result.transactionId[:], id)
+
+	return result
+}
+
 func (transactionMetadata *TransactionMetadata) IsSolid() (result bool) {
 	transactionMetadata.solidMutex.RLock()
 	result = transactionMetadata.solid
diff --git a/packages/storageprefix/storageprefix.go b/packages/storageprefix/storageprefix.go
index 7b2378eb5fadb2971676ba395af6e0104dfb4385..45bdcbfeab14e5b0577c4a04fa508233690223bb 100644
--- a/packages/storageprefix/storageprefix.go
+++ b/packages/storageprefix/storageprefix.go
@@ -4,6 +4,7 @@ var (
 	TangleTransaction         = []byte{0}
 	TangleTransactionMetadata = []byte{6}
 	TangleApprovers           = []byte{1}
+	TangleMissingTransaction  = []byte{7}
 
 	LedgerStateTransferOutput        = []byte{2}
 	LedgerStateTransferOutputBooking = []byte{3}