diff --git a/packages/ca/constants.go b/packages/ca/constants.go
index d995e27dfd9c2db0851c9cbfa15eb070c12d8a2d..2b31816a61193fb2b4d63799ea4350d228d72aa0 100644
--- a/packages/ca/constants.go
+++ b/packages/ca/constants.go
@@ -1,6 +1,8 @@
 package ca
 
 const (
-	MAX_STATEMENT_TIMEOUT = uint64(5000)
-	MAX_NEIGHBOR_COUNT    = 8
+	MAX_STATEMENT_TIMEOUT  = uint64(5000)
+	MAX_NEIGHBOR_COUNT     = 8
+	MAX_PENDING_HEARTBEATS = 10
+	MAX_MISSING_HEARTBEATS = 10
 )
diff --git a/packages/ca/errors.go b/packages/ca/errors.go
index 2fbec995bde3bf9e63639a6ad28a7029b9b30d55..86fa236cf80ecaa26c5280f280441b9fd4f795c0 100644
--- a/packages/ca/errors.go
+++ b/packages/ca/errors.go
@@ -5,6 +5,7 @@ import (
 )
 
 var (
+	ErrInternalError      = errors.New("internal error")
 	ErrMalformedHeartbeat = errors.New("malformed heartbeat")
 	ErrUnknownNeighbor    = errors.New("unknown neighbor")
 	ErrTooManyNeighbors   = errors.New("too many neighbors")
diff --git a/packages/ca/neighbor_manager.go b/packages/ca/neighbor_manager.go
index 900a905dc267f59d9b8f3098a7f78bc8ff1cfe2e..d5b77118f866000b2e5f7988e9d89b4cd6822152 100644
--- a/packages/ca/neighbor_manager.go
+++ b/packages/ca/neighbor_manager.go
@@ -5,6 +5,8 @@ import (
 	"sort"
 	"strconv"
 
+	"github.com/iotaledger/goshimmer/packages/typeutils"
+
 	"github.com/iotaledger/goshimmer/packages/events"
 
 	"github.com/iotaledger/goshimmer/packages/ca/heartbeat"
@@ -15,7 +17,7 @@ import (
 type NeighborManager struct {
 	Events                          NeighborManagerEvents
 	options                         *NeighborManagerOptions
-	lastAppliedHeartbeat            *heartbeat.Heartbeat
+	lastReceivedHeartbeat           *heartbeat.Heartbeat
 	missingHeartbeats               map[string]bool
 	pendingHeartbeats               map[string]*heartbeat.Heartbeat
 	heartbeats                      map[string]*heartbeat.Heartbeat
@@ -41,7 +43,7 @@ func (neighborManager *NeighborManager) Reset() {
 	neighborManager.neighborChains = make(map[string]*StatementChain)
 }
 
-func (neighborManager *NeighborManager) ApplyHeartbeat(heartbeat *heartbeat.Heartbeat) (err errors.IdentifiableError) {
+func (neighborManager *NeighborManager) storeHeartbeat(heartbeat *heartbeat.Heartbeat) (err errors.IdentifiableError) {
 	// region check if heartbeat is "syntactically correct" ////////////////////////////////////////////////////////////
 
 	mainStatement := heartbeat.GetMainStatement()
@@ -61,12 +63,48 @@ func (neighborManager *NeighborManager) ApplyHeartbeat(heartbeat *heartbeat.Hear
 	previousHeartbeatHash := mainStatement.GetPreviousStatementHash()
 	if len(previousHeartbeatHash) == 0 {
 		neighborManager.Reset()
-	} else if neighborManager.lastAppliedHeartbeat != nil && !bytes.Equal(neighborManager.lastAppliedHeartbeat.GetMainStatement().GetHash(), previousHeartbeatHash) {
+	} else if neighborManager.lastReceivedHeartbeat != nil {
+		lastMainStatement := neighborManager.lastReceivedHeartbeat.GetMainStatement()
+		previousHeartbeatHashString := typeutils.BytesToString(previousHeartbeatHash)
+		if lastMainStatement != nil && !bytes.Equal(lastMainStatement.GetHash(), previousHeartbeatHash) {
+			if len(neighborManager.pendingHeartbeats) >= MAX_PENDING_HEARTBEATS || len(neighborManager.missingHeartbeats) >= MAX_MISSING_HEARTBEATS {
+				neighborManager.Reset()
+			} else if _, exists := neighborManager.heartbeats[previousHeartbeatHashString]; !exists {
+				neighborManager.missingHeartbeats[previousHeartbeatHashString] = true
+			}
+		}
+	}
 
+	heartbeatHash := typeutils.BytesToString(mainStatement.GetHash())
+
+	if neighborManager.lastReceivedHeartbeat == nil || mainStatement.GetTime() > neighborManager.lastReceivedHeartbeat.GetMainStatement().GetTime() {
+		neighborManager.lastReceivedHeartbeat = heartbeat
 	}
 
+	neighborManager.heartbeats[heartbeatHash] = heartbeat
+	neighborManager.pendingHeartbeats[heartbeatHash] = heartbeat
+	delete(neighborManager.missingHeartbeats, heartbeatHash)
+
 	// endregion ///////////////////////////////////////////////////////////////////////////////////////////////////////
 
+	return
+}
+
+func (neighborManager *NeighborManager) applyPendingHeartbeats() (err errors.IdentifiableError) {
+	if len(neighborManager.missingHeartbeats) == 0 && len(neighborManager.pendingHeartbeats) >= 1 {
+		// cycle through heartbeats and apply them one by one
+	}
+
+	return
+}
+
+func (neighborManager *NeighborManager) ApplyHeartbeat(heartbeat *heartbeat.Heartbeat) (err errors.IdentifiableError) {
+	if storeErr := neighborManager.storeHeartbeat(heartbeat); storeErr != nil {
+		err = storeErr
+
+		return
+	}
+
 	// region mark idle neighbors //////////////////////////////////////////////////////////////////////////////////////
 
 	existingNeighbors := make(map[string]*StatementChain)