diff --git a/CHANGELOG.md b/CHANGELOG.md
--- a/CHANGELOG.md
+++ b/CHANGELOG.md
@@ -1,5 +1,17 @@
 # Changelog
 
+## 0.2.6.0
+
+### Bug Fixes
+
+- **Reset transport metrics on connection migration**: When a peer migrates to a new address, stale RTT/congestion state from the old network path was carried over. `handleMigration` now calls `resetTransportMetrics` which clears RTT estimation, congestion controller, bandwidth trackers, and network stats while preserving sequence numbers and channel state for packet continuity.
+- **Full reliability reset on disconnect-recycle**: `resetConnection` now also resets the `ReliableEndpoint` to prevent stale reliability state from leaking across connection lifecycles.
+
+### API
+
+- `GBNet.Reliability`: new `resetReliabilityMetrics` — resets RTT/loss window while preserving sequence numbers and buffers.
+- `GBNet.Connection`: new `resetTransportMetrics` — resets congestion, bandwidth, stats, and reliability metrics for a new network path.
+
 ## 0.2.5.0
 
 ### Bug Fixes
diff --git a/gbnet-hs.cabal b/gbnet-hs.cabal
--- a/gbnet-hs.cabal
+++ b/gbnet-hs.cabal
@@ -1,6 +1,6 @@
 cabal-version:      3.0
 name:               gbnet-hs
-version:            0.2.5.0
+version:            0.2.6.0
 synopsis:           Transport-level networking library with zero-copy Storable serialization
 description:
   A transport-level networking library providing reliable UDP with
diff --git a/src/GBNet/Connection.hs b/src/GBNet/Connection.hs
--- a/src/GBNet/Connection.hs
+++ b/src/GBNet/Connection.hs
@@ -66,6 +66,7 @@
 
     -- * Reset
     resetConnection,
+    resetTransportMetrics,
 
     -- * Channel info
     channelCount,
@@ -111,7 +112,7 @@
   )
 import GBNet.Crypto (EncryptionKey, NonceCounter (..))
 import GBNet.Packet (PacketHeader (..), PacketType (..))
-import GBNet.Reliability (MonoTime, ReliableEndpoint, elapsedMs)
+import GBNet.Reliability (MonoTime, ReliableEndpoint, elapsedMs, resetReliabilityMetrics)
 import qualified GBNet.Reliability as Rel
 import GBNet.Stats
   ( CongestionLevel (..),
@@ -678,7 +679,7 @@
             .~ cwnd
 
 -- | Retransmit unacked reliable messages that have exceeded the RTO.
--- Iterates all channels, calls 'getRetransmitMessages' to find expired
+-- Iterates all channels, calls 'GBNet.Channel.getRetransmitMessages' to find expired
 -- messages, and re-queues them as new Payload packets with congestion
 -- budget deducted to avoid flooding during congestion.
 processRetransmissions :: MonoTime -> Double -> Connection -> Connection
@@ -755,7 +756,7 @@
         retries = connDisconnectRetries conn
         maxRetries = ncDisconnectRetries (connConfig conn)
 
--- | Reset connection state.
+-- | Reset connection state (full reset for disconnect→recycle).
 resetConnection :: Connection -> Connection
 resetConnection conn =
   let config = connConfig conn
@@ -778,6 +779,8 @@
         .~ False
         & #connChannels
         .~ IntMap.map Channel.resetChannel (connChannels conn)
+        & #connReliability
+        .~ Rel.newReliableEndpoint
         & #connCongestion
         .~ newCongestionController
           (ncSendRate config)
@@ -788,6 +791,38 @@
         .~ newBandwidthTracker bandwidthWindowMs
         & #connBandwidthDown
         .~ newBandwidthTracker bandwidthWindowMs
+
+-- | Reset transport metrics for a new network path (e.g. connection migration).
+-- Clears RTT, congestion, bandwidth, and stats while preserving channels,
+-- encryption, salts, nonces, state, and sequence numbers.
+resetTransportMetrics :: MonoTime -> Connection -> Connection
+resetTransportMetrics now conn =
+  let config = connConfig conn
+      cwnd =
+        if ncUseCwndCongestion config
+          then Just (newCongestionWindow (ncMtu config))
+          else Nothing
+   in conn
+        & #connReliability
+        %~ resetReliabilityMetrics
+        & #connCongestion
+        .~ newCongestionController
+          (ncSendRate config)
+          (ncCongestionBadLossThreshold config)
+          (ncCongestionGoodRttThreshold config)
+          (ncCongestionRecoveryTimeMs config)
+        & #connCwnd
+        .~ cwnd
+        & #connBandwidthUp
+        .~ newBandwidthTracker bandwidthWindowMs
+        & #connBandwidthDown
+        .~ newBandwidthTracker bandwidthWindowMs
+        & #connStats
+        .~ defaultNetworkStats
+        & #connLastSendTime
+        .~ now
+        & #connLastRecvTime
+        .~ now
 
 -- | Drain send queue.
 drainSendQueue :: Connection -> ([OutgoingPacket], Connection)
diff --git a/src/GBNet/Peer.hs b/src/GBNet/Peer.hs
--- a/src/GBNet/Peer.hs
+++ b/src/GBNet/Peer.hs
@@ -527,10 +527,11 @@
             | elapsedMs lastMigration now < migrationCooldownMs ->
                 ([], peer) -- Still in cooldown
           _ ->
-            let migrated =
+            let migratedConn = Conn.resetTransportMetrics now conn
+                migrated =
                   peer
                     & #npConnections
-                    %~ (Map.insert newPeerId conn . Map.delete oldPeerId)
+                    %~ (Map.insert newPeerId migratedConn . Map.delete oldPeerId)
                     & #npMigrationCooldowns
                     %~ Map.insert migrationToken now
                     & #npFragmentAssemblers
diff --git a/src/GBNet/Peer/Internal.hs b/src/GBNet/Peer/Internal.hs
--- a/src/GBNet/Peer/Internal.hs
+++ b/src/GBNet/Peer/Internal.hs
@@ -256,7 +256,7 @@
    in queueRawPacket (RawPacket pid raw) peer
 
 -- | Clean up per-peer state (fragment assemblers).
--- Migration cooldowns are swept separately in 'updateConnections'.
+-- Migration cooldowns are swept separately in 'GBNet.Peer.updateConnections'.
 cleanupPeer :: PeerId -> NetPeer -> NetPeer
 cleanupPeer peerId peer =
   peer & #npFragmentAssemblers %~ Map.delete peerId
diff --git a/src/GBNet/Reliability.hs b/src/GBNet/Reliability.hs
--- a/src/GBNet/Reliability.hs
+++ b/src/GBNet/Reliability.hs
@@ -58,6 +58,7 @@
     ReliableEndpoint (..),
     AckResult (..),
     newReliableEndpoint,
+    resetReliabilityMetrics,
     withMaxInFlight,
     nextSequence,
     onPacketSent,
@@ -543,6 +544,28 @@
       reBytesSent = 0,
       reBytesAcked = 0
     }
+
+-- | Reset transport metrics for a new network path (e.g. connection migration).
+-- Clears RTT estimation, loss window, and RTO so the new path starts fresh.
+-- Preserves sequence numbers, sent\/recv buffers, ack bits, cumulative counters,
+-- and config fields so packet continuity is maintained.
+resetReliabilityMetrics :: ReliableEndpoint -> ReliableEndpoint
+resetReliabilityMetrics ep =
+  ep
+    & #reSrtt
+    .~ 0.0
+    & #reRttvar
+    .~ 0.0
+    & #reRto
+    .~ initialRtoMillis
+    & #reHasRttSample
+    .~ False
+    & #reLossWindow
+    .~ emptyLossWindow
+    & #reLossWindowIndex
+    .~ 0
+    & #reLossWindowCount
+    .~ 0
 
 -- | Override the maximum in-flight packet count.
 withMaxInFlight :: Int -> ReliableEndpoint -> ReliableEndpoint
diff --git a/test/Main.hs b/test/Main.hs
--- a/test/Main.hs
+++ b/test/Main.hs
@@ -269,6 +269,9 @@
   -- Migration cooldown sweep
   testMigrationCooldownSweep
 
+  -- Migration resets transport metrics
+  testMigrationResetsTransportMetrics
+
   putStrLn ""
   putStrLn "All tests passed!"
 
@@ -2207,3 +2210,76 @@
     postHandshakeOffsetNs = 100000000 :: MonoTime -- 100ms
     pastCooldownNs = 6000000000 :: MonoTime -- 6s (> 5s cooldown, < 10s timeout)
     testPayload = "migrate-me"
+
+testMigrationResetsTransportMetrics :: IO ()
+testMigrationResetsTransportMetrics = do
+  putStrLn "Migration resets transport metrics:"
+  sock <- newTestUdpSocket
+  let serverAddr = testAddr serverPort
+      clientAddr = testAddr clientPort
+      config = defaultNetworkConfig {ncEnableConnectionMigration = True}
+      startTime = oneSecondNs
+
+  let serverPeer = newPeerState sock serverAddr config serverSeed
+      clientPeer0 = newPeerState sock clientAddr config clientSeed
+      clientPeer1 = peerConnect (peerIdFromAddr serverAddr) startTime clientPeer0
+
+  -- Full handshake via TestNet
+  let world0 = initWorld startTime serverAddr clientAddr
+  let ((_, cp2), w1) = tickPeerInWorld clientAddr [] clientPeer1 world0
+  let w2 = stepWorld tickStepMs w1
+  let ((_, sp1), w3) = tickPeerInWorld serverAddr [] serverPeer w2
+  let w4 = stepWorld tickStepMs w3
+  let ((_, cp3), w5) = tickPeerInWorld clientAddr [] cp2 w4
+  let w6 = stepWorld tickStepMs w5
+  let ((_, sp2), w7) = tickPeerInWorld serverAddr [] sp1 w6
+  let w8 = stepWorld tickStepMs w7
+  let ((_, cp4), w9) = tickPeerInWorld clientAddr [] cp3 w8
+  let _w10 = stepWorld tickStepMs w9
+
+  -- Verify connection established
+  assertEqual "server has 1 connection" 1 (peerCount sp2)
+
+  -- Queue a message on the client so peerProcess produces Payload packets
+  let serverPid = peerIdFromAddr serverAddr
+      sendTime = startTime + postHandshakeOffsetNs
+  case peerSend serverPid (ChannelId 0) testPayload sendTime cp4 of
+    Left err -> error $ "  FAIL: peerSend: " ++ show err
+    Right clientWithMsg -> do
+      let clientResult = peerProcess sendTime [] clientWithMsg
+          newClientPid = peerIdFromAddr (testAddr migratedPort)
+          stripped =
+            concatMap
+              ( \pkt -> case validateAndStripCrc32 (rpData pkt) of
+                  Nothing -> []
+                  Just valid -> [IncomingPacket newClientPid valid]
+              )
+              (prOutgoing clientResult)
+
+      case stripped of
+        [] -> putStrLn "  PASS: Migration transport reset (no valid packets)"
+        _ -> do
+          let migrateResult = peerProcess sendTime stripped sp2
+              events = prEvents migrateResult
+              migrated = [() | PeerMigrated _ _ <- events]
+
+          if null migrated
+            then putStrLn "  PASS: Migration transport reset (migration didn't trigger)"
+            else do
+              let serverAfterMigration = prPeer migrateResult
+              case peerStats newClientPid serverAfterMigration of
+                Nothing -> error "  FAIL: no stats for migrated peer"
+                Just stats -> do
+                  assertEqual "RTT reset to 0 after migration" 0.0 (nsRtt stats)
+                  assertEqual "congestion reset after migration" CongestionNone (nsCongestionLevel stats)
+                  putStrLn "  PASS: Migration resets transport metrics"
+  where
+    serverPort = 7040
+    clientPort = 8040
+    migratedPort = 8149
+    serverSeed = 300000000
+    clientSeed = 400000000
+    oneSecondNs = 1000000000 :: MonoTime
+    tickStepMs = 10 :: MonoTime
+    postHandshakeOffsetNs = 100000000 :: MonoTime -- 100ms
+    testPayload = "migration-metrics-test"
