diff --git a/protocols/bgp/server/fsm.go b/protocols/bgp/server/fsm.go
index 2d1d3ce03c5ae7d3ff77198799440c6bf58e5ff1..115a1eafada9bd3ed486f68fc899315dc7cdc50e 100644
--- a/protocols/bgp/server/fsm.go
+++ b/protocols/bgp/server/fsm.go
@@ -46,8 +46,8 @@ type FSM struct {
 	connectRetryTimer   *time.Timer
 	connectRetryCounter int
 
-	holdTime  time.Duration
-	holdTimer *time.Timer
+	holdTime              time.Duration
+	lastUpdateOrKeepalive time.Time
 
 	keepaliveTime  time.Duration
 	keepaliveTimer *time.Timer
@@ -113,6 +113,10 @@ func newFSM(peer *peer) *FSM {
 	return f
 }
 
+func (fsm *FSM) updateLastUpdateOrKeepalive() {
+	fsm.lastUpdateOrKeepalive = time.Now()
+}
+
 func (fsm *FSM) addressFamily(afi uint16, safi uint8) *fsmAddressFamily {
 	if safi != packet.UnicastSAFI {
 		return nil
diff --git a/protocols/bgp/server/fsm_active.go b/protocols/bgp/server/fsm_active.go
index a84f910d945b473f655465239ae1b08c61d94ebc..b05d66ebad52f3f7ceb57fd295414d0c23b5fe82 100644
--- a/protocols/bgp/server/fsm_active.go
+++ b/protocols/bgp/server/fsm_active.go
@@ -3,7 +3,6 @@ package server
 import (
 	"fmt"
 	"net"
-	"time"
 )
 
 type activeState struct {
@@ -63,6 +62,5 @@ func (s *activeState) connectionSuccess(con net.Conn) (state, string) {
 		s.fsm.connectRetryCounter++
 		return newIdleState(s.fsm), fmt.Sprintf("Sending OPEN message failed: %v", err)
 	}
-	s.fsm.holdTimer = time.NewTimer(time.Minute * 4)
 	return newOpenSentState(s.fsm), "Sent OPEN message"
 }
diff --git a/protocols/bgp/server/fsm_connect.go b/protocols/bgp/server/fsm_connect.go
index 70142ea9702d2673f6c9a2450fc1ec2fb7f50c76..d8afdc7c57d0863d6dd7dcf479e6375011f3d8e0 100644
--- a/protocols/bgp/server/fsm_connect.go
+++ b/protocols/bgp/server/fsm_connect.go
@@ -3,7 +3,6 @@ package server
 import (
 	"fmt"
 	"net"
-	"time"
 )
 
 type connectState struct {
@@ -44,7 +43,6 @@ func (s *connectState) connectionSuccess(c net.Conn) (state, string) {
 	if err != nil {
 		return newIdleState(s.fsm), fmt.Sprintf("Unable to send open: %v", err)
 	}
-	s.fsm.holdTimer = time.NewTimer(time.Minute * 4)
 	return newOpenSentState(s.fsm), "TCP connection succeeded"
 }
 
diff --git a/protocols/bgp/server/fsm_established.go b/protocols/bgp/server/fsm_established.go
index ae4265e73cc3befe6110d2ca588f8de5001199a7..3152605151a56680fdb5e401cd5c198c26a0a0e3 100644
--- a/protocols/bgp/server/fsm_established.go
+++ b/protocols/bgp/server/fsm_established.go
@@ -4,6 +4,7 @@ import (
 	"bytes"
 	"fmt"
 	"net"
+	"time"
 
 	bnet "github.com/bio-routing/bio-rd/net"
 	"github.com/bio-routing/bio-rd/protocols/bgp/packet"
@@ -45,16 +46,24 @@ func (s establishedState) run() (state, string) {
 			default:
 				continue
 			}
-		case <-s.fsm.holdTimer.C:
-			return s.holdTimerExpired()
 		case <-s.fsm.keepaliveTimer.C:
 			return s.keepaliveTimerExpired()
+		case <-time.After(time.Second):
+			return s.checkHoldtimer()
 		case recvMsg := <-s.fsm.msgRecvCh:
 			return s.msgReceived(recvMsg, opt)
 		}
 	}
 }
 
+func (s *establishedState) checkHoldtimer() (state, string) {
+	if time.Since(s.fsm.lastUpdateOrKeepalive) > s.fsm.holdTime {
+		return s.holdTimerExpired()
+	}
+
+	return newEstablishedState(s.fsm), s.fsm.reason
+}
+
 func (s *establishedState) init() error {
 	host, _, err := net.SplitHostPort(s.fsm.con.LocalAddr().String())
 	if err != nil {
@@ -184,7 +193,7 @@ func (s *establishedState) notification() (state, string) {
 
 func (s *establishedState) update(u *packet.BGPUpdate) (state, string) {
 	if s.fsm.holdTime != 0 {
-		s.fsm.holdTimer.Reset(s.fsm.holdTime)
+		s.fsm.updateLastUpdateOrKeepalive()
 	}
 
 	if s.fsm.ipv4Unicast != nil {
@@ -240,7 +249,7 @@ func (s *establishedState) updateAddressFamily(u *packet.BGPUpdate) (afi uint16,
 
 func (s *establishedState) keepaliveReceived() (state, string) {
 	if s.fsm.holdTime != 0 {
-		s.fsm.holdTimer.Reset(s.fsm.holdTime)
+		s.fsm.updateLastUpdateOrKeepalive()
 	}
 	return newEstablishedState(s.fsm), s.fsm.reason
 }
diff --git a/protocols/bgp/server/fsm_open_confirm.go b/protocols/bgp/server/fsm_open_confirm.go
index 17df63c1a3481b09f6b1671ce412d761e27cf240..26c32ace0700b1daf4b1c6b0f71ddb5169cb4592 100644
--- a/protocols/bgp/server/fsm_open_confirm.go
+++ b/protocols/bgp/server/fsm_open_confirm.go
@@ -3,6 +3,7 @@ package server
 import (
 	"bytes"
 	"fmt"
+	"time"
 
 	"github.com/bio-routing/bio-rd/protocols/bgp/packet"
 )
@@ -31,8 +32,8 @@ func (s openConfirmState) run() (state, string) {
 			default:
 				continue
 			}
-		case <-s.fsm.holdTimer.C:
-			return s.holdTimerExpired()
+		case <-time.After(time.Second):
+			return s.checkHoldtimer()
 		case <-s.fsm.keepaliveTimer.C:
 			return s.keepaliveTimerExpired()
 		case recvMsg := <-s.fsm.msgRecvCh:
@@ -41,6 +42,14 @@ func (s openConfirmState) run() (state, string) {
 	}
 }
 
+func (s *openConfirmState) checkHoldtimer() (state, string) {
+	if time.Since(s.fsm.lastUpdateOrKeepalive) > s.fsm.holdTime {
+		return s.holdTimerExpired()
+	}
+
+	return newOpenConfirmState(s.fsm), s.fsm.reason
+}
+
 func (s *openConfirmState) manualStop() (state, string) {
 	s.fsm.sendNotification(packet.Cease, 0)
 	stopTimer(s.fsm.connectRetryTimer)
@@ -117,7 +126,7 @@ func (s *openConfirmState) notification(msg *packet.BGPMessage) (state, string)
 }
 
 func (s *openConfirmState) keepaliveReceived() (state, string) {
-	s.fsm.holdTimer.Reset(s.fsm.holdTime)
+	s.fsm.updateLastUpdateOrKeepalive()
 	return newEstablishedState(s.fsm), "Received KEEPALIVE"
 }
 
diff --git a/protocols/bgp/server/fsm_open_sent.go b/protocols/bgp/server/fsm_open_sent.go
index 8b306a2a3145bd5d7ac640f8e6fe31b50bcf7176..e7beb88363c4984fb7c9374da7e2efafeade01a4 100644
--- a/protocols/bgp/server/fsm_open_sent.go
+++ b/protocols/bgp/server/fsm_open_sent.go
@@ -38,14 +38,22 @@ func (s openSentState) run() (state, string) {
 			default:
 				continue
 			}
-		case <-s.fsm.holdTimer.C:
-			return s.holdTimerExpired()
+		case <-time.After(time.Second):
+			return s.checkHoldtimer()
 		case recvMsg := <-s.fsm.msgRecvCh:
 			return s.msgReceived(recvMsg, opt)
 		}
 	}
 }
 
+func (s *openSentState) checkHoldtimer() (state, string) {
+	if time.Since(s.fsm.lastUpdateOrKeepalive) > s.fsm.holdTime {
+		return s.holdTimerExpired()
+	}
+
+	return newOpenSentState(s.fsm), s.fsm.reason
+}
+
 func (s *openSentState) manualStop() (state, string) {
 	s.fsm.sendNotification(packet.Cease, 0)
 	s.fsm.resetConnectRetryTimer()
@@ -130,9 +138,7 @@ func (s *openSentState) openMsgReceived(openMsg *packet.BGPOpen) (state, string)
 func (s *openSentState) handleOpenMessage(openMsg *packet.BGPOpen) (state, string) {
 	s.fsm.holdTime = time.Duration(math.Min(float64(s.fsm.peer.holdTime), float64(time.Duration(openMsg.HoldTime)*time.Second)))
 	if s.fsm.holdTime != 0 {
-		if !s.fsm.holdTimer.Reset(s.fsm.holdTime) {
-			<-s.fsm.holdTimer.C
-		}
+		s.fsm.updateLastUpdateOrKeepalive()
 		s.fsm.keepaliveTime = s.fsm.holdTime / 3
 		s.fsm.keepaliveTimer = time.NewTimer(s.fsm.keepaliveTime)
 	}
diff --git a/protocols/bgp/server/fsm_test.go b/protocols/bgp/server/fsm_test.go
index 86a8fd78c305781d190ba9cc33811c709e146e34..62a1c1428ceda110e34c34e0241d659c463499f8 100644
--- a/protocols/bgp/server/fsm_test.go
+++ b/protocols/bgp/server/fsm_test.go
@@ -24,7 +24,7 @@ func TestFSM255UpdatesIPv4(t *testing.T) {
 		},
 	})
 
-	fsmA.holdTimer = time.NewTimer(time.Second * 90)
+	fsmA.holdTime = time.Second * 180
 	fsmA.keepaliveTimer = time.NewTimer(time.Second * 30)
 	fsmA.connectRetryTimer = time.NewTimer(time.Second * 120)
 	fsmA.state = newEstablishedState(fsmA)
@@ -112,11 +112,11 @@ func TestFSM255UpdatesIPv4(t *testing.T) {
 			b + 25, 169, a, i, 0,
 			0, 0,
 		}
+
 		fsmA.msgRecvCh <- update
 		ribRouteCount = fsmA.ipv4Unicast.rib.RouteCount()
 	}
 	time.Sleep(time.Second * 1)
-
 	ribRouteCount = fsmA.ipv4Unicast.rib.RouteCount()
 	if ribRouteCount != 0 {
 		t.Errorf("Unexpected route count in LocRIB: %d", ribRouteCount)
@@ -139,7 +139,7 @@ func TestFSM255UpdatesIPv6(t *testing.T) {
 	})
 
 	fsmA.ipv6Unicast.multiProtocol = true
-	fsmA.holdTimer = time.NewTimer(time.Second * 90)
+	fsmA.holdTime = time.Second * 180
 	fsmA.keepaliveTimer = time.NewTimer(time.Second * 30)
 	fsmA.connectRetryTimer = time.NewTimer(time.Second * 120)
 	fsmA.state = newEstablishedState(fsmA)
diff --git a/protocols/bgp/server/update_sender_test.go b/protocols/bgp/server/update_sender_test.go
index 4e75183a294384446b57684566a35273611966ed..1d4d97fd4f2735283327341ade693344ecd484b4 100644
--- a/protocols/bgp/server/update_sender_test.go
+++ b/protocols/bgp/server/update_sender_test.go
@@ -897,7 +897,6 @@ func TestSender(t *testing.T) {
 			fsmA.ipv4Unicast.addPathTX = test.addPath
 		}
 
-		fsmA.holdTimer = time.NewTimer(time.Second * 90)
 		fsmA.keepaliveTimer = time.NewTimer(time.Second * 30)
 		fsmA.connectRetryTimer = time.NewTimer(time.Second * 120)
 		fsmA.state = newEstablishedState(fsmA)