RFC 9959
Careful Resume: Convergence of Congestion Control from Retained State
Careful Resume: Convergence of Congestion Control from Retained State ๐ธ
RFC 9959 โจ is a Standards Track doc from the IETF (Internet Engineering Task Force) ๐, dated May 2026, with ISSN 2070-1721. The authors are N. Kuhn (Thales Alenia Space), E. Stephan (Orange), G. Fairhurst and R. Secchi (University of Aberdeen), and C. Huitema (Private Octopus Inc.) ๐ซถ. It doesn't list anything it obsoletes or updates, so it's standing on its own ๐ .
Abstract ๐ฆ
This doc is a spec for a cautious method for Internet transports that gives connections a fast startup of Congestion Control (CC) across a wide range of connections, which they call "Careful Resume" โจ. It reuses a set of computed CC parameters that are based on previously observed path characteristics between the same pair of transport endpoints. These parameters get saved, so they can be used later to modify the CC behaviour of a subsequent connection ๐ง.
The doc describes the assumptions and sets out the requirements for how a sender uses these parameters, so a connection can get up to speed faster and make use of available capacity ๐. It also talks about how this method affects the capacity at a shared network bottleneck, and the safe response needed after any sign that the new rate is inappropriate ๐.
Status of This Memo ๐
This is an Internet Standards Track document.
This document is a product of the Internet Engineering Task Force (IETF) ๐. It represents the consensus of the IETF community. It has received public review and has been approved for publication by the Internet Engineering Steering Group (IESG). Further information on Internet Standards is available in Section 2 of RFC 7841 ๐.
Information about the current status of this document, any errata, and how to provide feedback on it may be obtained at https://www.rfc-editor.org/info/rfc9959 ๐.
Copyright Notice ยฉ๏ธ
Copyright (c) 2026 IETF Trust and the persons identified as the document authors. All rights reserved ๐.
This document is subject to BCP 78 and the IETF Trust's Legal Provisions Relating to IETF Documents (https://trustee.ietf.org/license-info) in effect on the date of publication of this document. Please review these documents carefully, as they describe your rights and restrictions with respect to this document. Code Components extracted from this document must include Revised BSD License text as described in Section 4.e of the Trust Legal Provisions and are provided without warranty as described in the Revised BSD License ๐.
Table of Contents ๐บ๏ธ
1. Introduction
1.1. Use of Saved CC Parameters by a Sender
1.2. Receiver Preference
1.3. Transport Protocol Interaction
1.4. Examples of Scenarios of Interest
1.5. Design Principles
2. Language, Notation, and Terms
2.1. Requirements Language
2.2. The Remote Endpoint
2.3. Logging Support
2.4. Notation and Terms
3. The Phases of CC Using Careful Resume
3.1. Observing
3.2. Reconnaissance Phase
3.3. Unvalidated Phase
3.4. Validating Phase
3.5. Safe Retreat Phase
3.6. Detecting Persistent Congestion While Using Careful Resume
3.7. Returning to Use Normal CC
4. Implementation Notes and Guidelines
4.1. Observing the Path Capacity
4.2. Confirming the Path in the Reconnaissance Phase
4.2.1. Confirming the Path
4.3. Safety in the Unvalidated Phase
4.3.1. Lifetime of CC Parameters
4.3.2. Pacing in the Unvalidated Phase
4.3.3. Exit from the Unvalidated Phase Because of Variable
Network Conditions
4.4. The Validating Phase
4.5. Safety in the Safe Retreat Phase
4.6. Returning to Normal Congestion Control
4.7. Limitations from Transport Protocols
5. Operational Considerations
6. IANA Considerations
7. Security Considerations
8. References
8.1. Normative References
8.2. Informative References
Appendix A. Notes on the Careful Resume Phases
Appendix B. Examples of the Careful Resume Phases
B.1. Example with No Loss
B.2. Example with No Loss, Rate Limited
B.3. Example with Loss Detected in the Reconnaissance Phase
B.4. Example with Loss Detected in the Validating Phase
Appendix C. Implementation Notes for Using BBR
C.1. Sending Unvalidated Packets Using BBR
C.2. Validation for BBR
C.3. Safe Retreat for BBR
Acknowledgments
Authors' Addresses
1. Introduction โจ
Okay so every Internet transport has to either run a Congestion Control (CC) algorithm or constrain how fast it sends [RFC2914] [RFC8085] ๐ซถ. Back in 2010, a survey of alternative CC algorithms [RFC5783] pointed out that things get messy when a CC algorithm runs over an Internet path with a high and/or varying Bandwidth-Delay Product (BDP) ๐ญ. This doc is aimed at solving exactly those problems ๐ .
A CC algorithm usually takes time to ramp up its sending rate ๐ข. This is called the "Slow Start Phase," and people informally call it the time to "get up to speed." During this time a sender deliberately uses less capacity than might be available, so it can avoid or limit overshooting the capacity the path has โจ. In the context of CC, a path is the end-to-end communication between a pair of transport endpoints, each identified by a source IP address and a unicast or anycast destination IP address. (This doc doesn't define support for broadcast or multicast destination addresses ๐ .) A path can also be linked to a specific Differentiated Services Code Point (DSCP) ๐. Below the transport layer, a specific path could be realised in various ways, but the transport endpoints don't normally see this ๐. (When it's known, extra path information could potentially give the CC algorithm an explicit signal, so it can notice when the path changes ๐.)
Overshooting the bottleneck rate can really hurt other flows that share the same bottleneck ๐. A sender can also use a method that watches the rate of acknowledged data, to try to avoid overshooting this bottleneck capacity (for example, Hystart++ [RFC9406]) ๐.
In the extreme case, an overshoot can cause persistent congestion, starving other flows that share a common capacity bottleneck. That means the other flows can't successfully share the capacity at that bottleneck [RFC2914] ๐ฑ.
Normally a separate instance of a CC algorithm runs over each transport path ๐ค๏ธ. This tries to stop queuing (latency or jitter) and/or congestion packet loss from going up for the flow ๐. With a multipath transport, there can be more than one path, each with its own separate CC context ๐.
This document specifies Careful Resume ๐ฆ, a method that tries to cut the time needed to finish a transfer when the congestion controller limits the sending rate using the congestion window (CWND). Specifically, this is when a transfer wants to send a lot more data than the initial congestion window (IW) allows, and the BDP of the path is also a lot bigger than the product of the IW and the path Round Trip Time (RTT) ๐ซ.
Careful Resume offers an alternative way to pick the initial CC parameters, one that aims to grow the sending rate controlled by the CWND faster and more safely ๐.
Careful Resume is based on temporal sharing (sometimes called "caching") of a saved set of CC parameters, which relate to earlier observations of the same path ๐ง . The parameters are saved and then used to modify the CC behaviour of a later connection between the same endpoints ๐.
Rate-based CC algorithms can make similar adjustments to their target sending rate ๐ฏ. When saving the observed capacity, some CC algorithms might save a different parameter that's equivalent to the saved_cwnd. For example, a rate-based CC algorithm such as Bottleneck Bandwidth and Round-trip propagation time (BBR) [BBR-CC] can keep the value of the bottleneck bandwidth needed to reach the capacity available to the flow (for example, BBR.max_bw) ๐.
1.1. Use of Saved CC Parameters by a Sender ๐
Careful Resume uses CC parameters for three jobs:
- Information to confirm whether a saved path matches the current path.
- Information about the utilised path capacity and observed RTT, used to set CC parameters for the current connection.
- Information to check the CC parameters aren't too old.
CC algorithms need to be careful when they use saved CC parameters on a new path (see [RFC9000] and [RFC9040]) ๐ง. So care is needed to make sure it's used safely, and to hold up when traffic patterns, network routing, or link/node conditions change ๐ก๏ธ. Sometimes using the saved parameters from an earlier connection just isn't appropriate (see Section 4) ๐ โโ๏ธ.
1.2. Receiver Preference ๐โโ๏ธ
A sender could make optimisation decisions without thinking about the receiver's preference. Still, there are cases where a receiver has information the sender doesn't, or might benefit from knowing that Careful Resume could be used ๐งฉ. In those cases, a receiver could use a transport mechanism to explicitly ask to either enable or inhibit Careful Resume when an application starts a new connection ๐ฌ.
A receiver might want to inhibit Careful Resume in some situations, for example:
- when a receiver can predict the pattern of traffic (for example, insight into the volume of data to be sent, the expected length of a connection, or the requested maximum transfer rate) ๐;
- when a receiver has a local indication that a path/local interface has changed since the CC parameters were saved ๐;
- when a receiver knows about the current hardware limitations ๐ฅ๏ธ;
- when a receiver can predict that additional capacity will be needed for other concurrent or later flows (that is, it prefers to turn on Careful Resume for a different connection) ๐ซ .
1.3. Transport Protocol Interaction ๐ค
The CWND is one factor that limits the sending rate of a transport protocol ๐ฆ. Other mechanisms also cap the maximum sending rate. These include the sender pacing rate, and the receiver-advertised window [RFC9293] or flow control credit [RFC9000]. See Section 4.7 for more on that ๐.
1.4. Examples of Scenarios of Interest โจ
Okay bestie, this part shows where Careful Resume is expected to glow up performance ๐ฆ Either endpoint can be the sender or the receiver ๐ and it can be used independently for each direction of a bidirectional connection.
Scenario one: an app keeps opening connections over the same path. Without a new method, every connection has to work out the right CC parameters from scratch ๐ฉ With Careful Resume, the flow can use a rate based on the CC parameters it already observed. Main character efficiency ๐
Scenario two: an app reconnects after a disruption temporarily reduced the path capacity. When this endpoint comes back to the path using Careful Resume, the sending rate can be based on the previously observed CC parameters ๐
The biggest win is on paths with a much larger RTT than typical Internet paths ๐ฐ๏ธ In one example, an app on a geo-stationary satellite access network [IJSCN] could take 9 seconds to finish a 5.3 MB transfer with standard CC, while a sender using Careful Resume could bring that down to 4 seconds ๐ญ A 1 MB transfer could also be reduced by 62 % [MAPRG111]. This benefit is also expected for other transfer sizes and different path characteristics when a path has a large BDP โก [CR25] has more discussion of the method in this document, including analysis over various types of paths ๐
1.5. Design Principles ๐ง
Resuming a connection with CC parameters observed during a previous connection is honestly a tradeoff ๐ฌ You get potential performance gains for the new connection, but you risk degrading performance for other connections that share a common bottleneck. The specified method aims for good performance when resuming is appropriate, while seeking to minimise the impact on other connections when it isn't ๐ซถ
The following precautions reduce the risk of a sender adding excessive congestion to a path:
- First, check whether conditions have changed so much that the saved values are no longer valid. We call this the "Reconnaissance Phase" ๐ต๏ธโโ๏ธ During that phase, the sender will not send more data than allowed for any new connection, e.g., using the recommended maximum IW for the first RTT of transmitting data [RFC6928] [RFC9002]. The sender will only proceed with the resume process if the reconnaissance succeeds. If it fails (for example, if previous packets in a connection experience congestion or the RTT is significantly different), the sender follows the standard process for a new connection. This gives some protection against making severe congestion worse and lets the sender establish the minimum RTT โ
- Second, use the saved parameters cautiously when resuming. This is called the "Unvalidated Phase" ๐ฅบ For example, the jump in the size of CWND/rate is restricted to a fraction (1/2) of the saved_cwnd, so other flows that may have started or increased their capacity after the last capacity measurement don't get starved. The same principle applies to CC algorithms that use different parameters than classic TCP CC: i.e., a sender must not send faster than allowed by a fraction of the saved CC parameters. For example, a connection using a rate-based CC algorithm (e.g., BBR) will set the pacing rate to half the remembered value of the "bottleneck bandwidth". The sender also needs to pace all unvalidated packets, to ensure the rate does not exceed the previously used rate. This is intended to avoid a sudden influx of packets that could build a bottleneck queue and disrupt existing flows ๐ Successful validation can allow further increases of the CWND, after first validating that the used rate did not result in congestion.
- Third, enter a "Safe Retreat Phase" if validation fails, for example, if congestion is detected during validation ๐โโ๏ธ The risk here is that the trial use of the saved CC parameters could have disrupted existing connections. For example, consider a connection using Reno CC: when exiting "Slow Start" mode due to loss, Reno would normally update the CWND to a "Slow Start threshold" set to half the volume of data in flight. However, during this validation, the CWND is restored from the saved CC parameters. The resultant sending rate could be much larger than the value a "standard" Slow Start process would have reached, which could overload the path and cause significant congestion to other flows ๐ฅ Instead of continuing with that "too large" value, the retreat process resets the congestion window (rate) to a value no greater than what a standard process would have discovered. For other CC algorithms, such as CUBIC [RFC9438] or BBR, the implementation details may differ, but the principle remains: trying and failing should not unduly disadvantage existing connections that share a common bottleneck (e.g., resulting in starving these connections) ๐ซถ
2. Language, Notation, and Terms ๐
This section gives a brief summary of key terms and the requirements language ๐
2.1. Requirements Language
The key words "MUST", "MUST NOT", "REQUIRED", "SHALL", "SHALL NOT", "SHOULD", "SHOULD NOT", "RECOMMENDED", "NOT RECOMMENDED", "MAY", and "OPTIONAL" in this document are to be interpreted as described in BCP 14 [RFC2119] [RFC8174] when, and only when, they appear in all capitals, as shown here ๐ฃ
2.2. The Remote Endpoint ๐
The Remote Endpoint is an implementation-dependent value that identifies the sender's view of the network path being used. It's used to match the current path with a set of CC parameters associated with a previously observed path. It includes:
- an identifier representing the sending interface (e.g., a globally assigned address/prefix or other local identifier);
- an identifier representing the destination (e.g., a unicast or anycast IP address).
The Remote Endpoint could also include information such as the DSCP. If included, that information needs to be set consistently for a resumed connection to the same endpoint. Although additional information could improve the path differentiation, it could reduce the reusability of saved parameters ๐ค
The saved CC parameters can only be used to modify the startup when the Remote Endpoint is not known to have changed (see Section 3.2).
2.3. Logging Support ๐
This document defines triggers to support logging key events. For example, [LOG] provides definitions that enable a Careful Resume implementation to generate QLOG events when using QUIC ๐ชต
2.4. Notation and Terms ๐
The document uses language drawn from a range of RFCs. The following terms are defined:
- ACK: The indication at the transport layer that the Remote Endpoint has correctly received the acknowledged data. In a CC algorithm, an ACK also confirms that the acknowledged data is no longer in flight.
- Beta: A scaling factor between 0.5 and 1; the default value is 0.5.
- Careful Resume: The method specified in this document to select initial CC parameters and to more rapidly and safely increase the initial sending rate.
- Congestion Control (CC) parameters: A set of saved CC parameters from observing the capacity of an established connection (see Section 1.1).
- congestion window (CWND): The congestion window or equivalent CC variable limiting the maximum sending rate (see [RFC5681]).
- current Round Trip Time (RTT): A sample measurement of the current RTT measured using the most recent ACK.
flight_size: The current volume of unacknowledged data (see [RFC5681]).jump_cwnd: The resumed CWND, used in the Unvalidated Phase.- Lifetime: The configured time after which a set of saved CC parameters can no longer be safely reused.
max_jump: The configured maximumjump_cwnd.- PipeSize: A measure of the validated available capacity based on the acknowledged data.
- Remote Endpoint: The endpoint corresponding to a connection; see Section 2.2.
saved_cwnd: A CC parameter with the preserved capacity derived from observation of a previous connection (see Section 4.1).saved_remote_endpoint: The Remote Endpoint that was associated with a set of saved CC parameters.saved_rtt: A CC parameter with the preserved minimum RTT (see Section 4.1).- unvalidated packet: A packet sent when the CWND has been increased beyond the size normally permitted by the CC algorithm; if such a packet is acknowledged by an ACK, it contributes to the PipeSize, but if congestion is detected, it triggers entry to the Safe Retreat Phase.
3. The Phases of CC Using Careful Resume ๐ฆ
This section defines a series of phases that the congestion controller moves through as a connection uses Careful Resume. Each rule is prefixed by the name of the relevant phase ๐บ๏ธ
Normal CC...> Connect -> Reconnaissance --------------------> Normal CC
(Observing) | ^
v |
Unvalidated --------------------------+
| | |
| +--> Validating --------------+
| | |
| | |
+---------------+--> Safe Retreat ---+
Figure 1: Key Transitions Between Phases in Careful Resume
The key phases of Careful Resume are illustrated in Figure 1. Examples of transitions between these phases are provided in Appendices A and B.
3.1. Observing ๐
An established connection can save a set of CC parameters for the specific path to the current endpoint. A set of CC parameters includes a Lifetime (e.g., as a timestamp after which the parameters must not be used) and corresponds to one saved_remote_endpoint.
The following rules apply to observing a connection:
- Observing (
saved_cwnd): The currently utilised capacity for the connection is measured as the volume of bytes sent during an RTT and is recorded in thesaved_cwnd. This could be computed by measuring the volume of data acknowledged in one RTT. If the measured CWND is less than four times the IW, the sender can choose to not save the CC parameters, because the additional actions associated with performing Careful Resume for a small CWND would not justify its use. - Observing (
saved_rtt): The minimum RTT at the time of observation is saved as thesaved_rtt. - Observing (updating saved CC parameters): A sender MUST NOT retain more than one set of CC parameters for a Remote Endpoint, but the set of CC parameters SHOULD be updated (or replaced) after a later observation of a path to the same Remote Endpoint. ๐ฅ
Implementation notes are provided in Section 4.1.
3.2. Reconnaissance Phase โจ
okay bestie, so this phase is where the sender goes digging for its saved CC parameters ๐ต๏ธโโ๏ธ and checks whether the path looks like the one it saw before. Basically it's matching the saved_remote_endpoint in the saved set, no cap. It's giving detective energy.
The sender enters the Reconnaissance Phase after connection setup, and it starts out with normal CC. In this phase the CWND gets set to the IW, and then the sender sends any initial data it has ๐
In the Reconnaissance Phase, there's just one action the sender takes:
- Reconnaissance Phase (received acknowledgment): The CWND grows using normal CC each time an ACK confirms delivery of data that wasn't acknowledged before. So the base CC algorithm just keeps doing its thing, totally normal ๐
The sender leaves the Reconnaissance Phase and stops using Careful Resume when any of these things happen:
- Reconnaissance Phase (detected congestion): If the sender spots congestion (like packet loss or an ECN-CE mark), that's a big sign the saved CC parameters aren't it for this path ๐ฌ So the sender stops using Careful Resume and MUST continue using normal CC to deal with the congestion. Iconic self-preservation ๐ก๏ธ
- Reconnaissance Phase (using saved_cwnd): Only one connection can use a given set of saved CC parameters, bestie, no sharing ๐
โโ๏ธ If another connection has already started using the
saved_cwnd, the sender MUST exit Careful Resume and go back to normal CC. - Reconnaissance Phase (path change): If the Remote Endpoint isn't the same as any
saved_remote_endpoint, or the local stack signals that the path is different from the one that was observed, the sender MUST stop using Careful Resume and returns to use normal CC. Not the same path? Not the same vibe ๐ - Reconnaissance Phase (lifetime of saved CC parameters): The CC parameters have an expiry date, literally โณ If the Lifetime of the observed CC parameters gets exceeded, that set isn't used anymore. The saved CC parameters get deleted, and the sender MUST stop using Careful Resume and return to using normal CC. Old news, gone ๐๏ธ
- Reconnaissance Phase (minimum RTT too small): If the minimum RTT recorded in the Reconnaissance Phase is less than or equal to (
saved_rtt / 2) (see Section 4.2.1), the sender MUST stop using Careful Resume (for example, logged asrtt_not_validatedin [LOG]) and returns to use normal CC. The reason this matters is that a sending rate calculated from asaved_cwnddepends directly on the RTT, so a big change in RTT is a strong sign the old CC parameters don't fit the current path anymore ๐
Note: When a path is not confirmed, Careful Resume doesn't change the CWND before it exits to normal CC. Nothing gets touched, it just bounces ๐ซถ
The sender is allowed to enter the Unvalidated Phase, as described below:
- Reconnaissance Phase (path confirmed): Once the sender gets an ACK that acknowledges all the initial data (usually the IW) without any reported congestion, it MAY then enter the Unvalidated Phase. A sender can jump over to the Unvalidated Phase right away, but it MAY also wait until it's about to send more data than the CC algorithm would normally allow. Either way is valid, bestie ๐ฆ
Implementation notes are provided in Section 4.2.
3.3. Unvalidated Phase
The Unvalidated Phase is designed to help the CWND get up to speed faster, by using paced transmission of a tentatively increased CWND ๐๏ธ๐จ It's the "let's test the waters" moment.
When the sender enters the Unvalidated Phase, these actions happen:
- Unvalidated Phase (initialising PipeSize): The variable
PipeSizegets set to theflight_sizeas soon as the sender enters the Unvalidated Phase. This records the portion of the CWND that was actually in use before the jump is applied ๐ - Unvalidated Phase (setting the jump_cwnd): To avoid starving other flows that might have started, or increased their use of capacity, since the path's capacity was observed, the
jump_cwndMUST be no more than half of thesaved_cwnd. Sojump_cwndis less than or equal toMin(max_jump,(saved_cwnd/2)), and thenCWND = jump_cwnd. Sharing is caring ๐ซฑ๐ซฒ
In the Unvalidated Phase, the sender does these things:
- Unvalidated Phase (pacing transmission): Every packet sent during the Unvalidated Phase MUST use pacing based on the current RTT. No bursting allowed, bestie ๐
- Unvalidated Phase (tracking PipeSize): The
PipeSizegoes up by the amount of data that each received ACK newly acknowledges. This tells the sender that a previously unvalidated packet made it across the path successfully ๐
The sender leaves the Unvalidated Phase and enters the Safe Retreat Phase when any of these happen:
- Unvalidated Phase (confirming the path during transmission): If the sender decides it isn't valid to use the previous CC parameters, because it detected a path change (for example, a change in the RTT or an explicit signal that the path changed), the Safe Retreat Phase MUST be entered (for example, logged as
path_changedin [LOG]). Path's not the same, we retreat ๐โโ๏ธ - Unvalidated Phase (detected congestion): If the sender detects congestion (for example, packet loss or ECN-CE marking), the Safe Retreat Phase MUST be entered (for example, logged as either
packet_lossorECN_CEin [LOG]). Note that not enough time has gone by in the Unvalidated Phase for the sender to hear any feedback that validates the jump in the CWND. So any congestion it detects has to come from packets sent before the Unvalidated Phase started ๐ค
The sender leaves the Unvalidated Phase and checks whether to enter the Validating Phase when any of these happen:
- Unvalidated Phase (completed sending all unvalidated packets): The sender enters the Validating Phase when the
flight_sizeequals the CWND (for example, logged aslast_unvalidated_packet_sentin [LOG]). If the implementation measures the CWND in bytes, this is also true when the unused part of the CWND is smaller than one maximum-sized packet. Close enough, we're done sending ๐ - Unvalidated Phase (receiving acknowledgment for an unvalidated packet): The sender enters the Validating Phase when it gets an ACK that acknowledges the first packet number (or a higher one) that was sent in the Unvalidated Phase (for example, logged as
first_unvalidated_packet_acknowledgedin [LOG]). First one's home safe ๐ก - Unvalidated Phase (limiting time in the Unvalidated Phase): The sender enters the Validating Phase if more than one RTT has passed while it's been in the Unvalidated Phase (for example, logged as
rtt_exceededin [LOG]). Time's up, babe โฐ
Unvalidated Phase (check flight_size): Whenever any of those events happen, and after the sender has processed any Acknowledgments that update the PipeSize and flight_size, it checks two things. If the flight_size is less than the IW, or the flight_size is less than or equal to the PipeSize, then it resets the CWND to the PipeSize (for example, logged as rate_limited in [LOG]), stops using Careful Resume, and goes back to normal CC. Without any detected congestion, the CWND never drops below the IW ๐ The PipeSize doesn't count the part of the jump_cwnd that wasn't used. Otherwise, the CWND MUST be set to the flight_size and the sender moves on to the Validating Phase. Main character moment, but make it responsible ๐
Implementation notes are provided in Section 4.3.
Notes for BBR are provided in Appendix C.1.
3.4. Validating Phase
The Validating Phase checks whether all the packets sent in the Unvalidated Phase got through without causing congestion ๐ The CWND stays unvalidated, and the sender usually hangs out in this phase for about one RTT.
In the Validating Phase, the sender does these things:
- Validating Phase (tracking PipeSize): The
PipeSizegoes up by the amount of acknowledged data for each received ACK that shows a packet made it across the path successfully ๐ - Validating Phase (updating the CWND): The CWND gets updated using the normal rules of the current congestion controller. This typically uses "Slow Start", which lets the CWND grow for each received ACK that shows a packet was successfully sent across the path. Growth arc unlocked ๐ฑ
The sender leaves the Validating Phase when any of these happen:
- Validating Phase (detected congestion): If the sender determines that congestion was detected (for example, packet loss or ECN-CE marking), Careful Resume enters the Safe Retreat Phase (for example, logged as either
packet_lossorECN_CEin [LOG]). Congestion? Retreat, no debate ๐ โโ๏ธ - Validating Phase (receiving acknowledgment of the unvalidated packets): The sender stops using Careful Resume when it gets an ACK that acknowledges the last packet number (or a higher one) that was sent in the Unvalidated Phase (for example, logged as
last_unvalidated_packet_acknowledgedin [LOG]). This means the packets sent in the Unvalidated Phase were all acknowledged without congestion. We did it, we're so back ๐ฅนโจ
Notes for BBR are provided in Appendix C.2.
3.5. Safe Retreat Phase
This phase gets entered when congestion is detected for an unvalidated packet. Its job is to drain the path of the other unvalidated packets ๐งน Clean up time.
When the sender enters the Safe Retreat Phase, these actions happen:
- Safe Retreat Phase (removing saved information): The set of saved CC parameters for the path gets deleted, so later flows can't use them again ๐ซ
- Safe Retreat Phase (re-initializing the CWND): The CWND MUST be reduced to no more than (
PipeSize/2). This avoids persistent starvation, because it leaves room for other flows to get their fair share of the total capacity back ๐ (Note: The minimum CWND in QUIC is 2 packets; see [RFC9002], Section 4.8.) - Safe Retreat Phase (loss recovery): Loss recovery starts using the newly reduced CWND that got set when the sender entered the Safe Retreat Phase. When the CWND is reduced, a QUIC sender can immediately send a single packet before the reduction [RFC9002] to speed up loss recovery. A similar method for TCP is described in Section 5 of [RFC6675]. Loss recovery keeps going until the last packet number (or a later one) sent in the Unvalidated or Validating Phase gets acknowledged. (Note: If the last unvalidated packet isn't cumulatively acknowledged, then some extra packets might also need to be retransmitted ๐)
In the Safe Retreat Phase, the sender does these things:
- Safe Retreat Phase (tracking PipeSize): The sender keeps updating the
PipeSizeafter it processes each ACK. ThePipeSizegets used to update the ssthresh when leaving this phase, but it doesn't affect the CWND ๐ - Safe Retreat Phase (maintaining the CWND): The CWND MUST NOT be increased in the Safe Retreat Phase. No growing allowed here, bestie ๐ โโ๏ธ
- Safe Retreat Phase (acknowledgment of unvalidated packets): When the last packet (or a later one) sent during the Unvalidated Phase gets acknowledged, the sender stops using Careful Resume and goes back to normal CC. Finally, we're free ๐๏ธ
When leaving the Safe Retreat Phase, the ssthresh MUST be set to no larger than the most recently measured PipeSize * Beta, where Beta is a scaling factor between 0.5 and 1. The default value is 0.5, which was picked to reduce the chance of causing a second round of congestion. CUBIC defines a Beta__cubic of 0.7 [RFC9438] (for example, logged as exit_recovery in [LOG]). Gentle exit, zero drama ๐ธ
Implementation notes are provided in Section 4.5.
Notes for BBR are described in Appendix C.3.
3.6. Detecting Persistent Congestion While Using Careful Resume ๐จ
okay so bestie, if a sender hits persistent congestion (like a Retransmission Time Out (RTO) or expiry in TCP) it's time to ditch Careful Resume ๐ The sender stops using it and goes back to normal CC. ๐ซถ If it's using BBR, the normal way it handles packet losses will push it into the Drain state while the "carefully-resuming" flag is set to True. (See Appendix C.3 for the deets! ๐)
ngl this part is so important: just like in loss recovery, data sent in the Unvalidated Phase could still get acknowledged later, after an RTO event. ๐ Not me noticing this at 2am ๐ญ
3.7. Returning to Use Normal CC ๐ฆ
once Careful Resume is over, the sender goes back to the normal CC algorithm, no cap ๐ That means congestion avoidance when the CWND is more than ssthresh, or Slow Start when it's less than or equal to ssthresh. โจ
implementation notes are coming up in Section 4.6 ๐
4. Implementation Notes and Guidelines ๐ง
this section is all about the practical stuff for implementing and using Careful Resume. it's giving "how to actually build this," so pay attention, bestie ๐
4.1. Observing the Path Capacity ๐
there are a bunch of ways to measure how much capacity a connection is using ๐ค Congestion controllers like Reno [RFC5681] or CUBIC [RFC9438] could estimate it from the CWND, flight_size, the acknowledged rate, etc. ๐ A different approach works for rate-based congestion controllers like BBR [BBR-CC], or it could just observe the rate at which data gets acknowledged by the Remote Endpoint. ๐
implementations are required to calculate a saved_rtt, which is the minimum RTT measured while observing the capacity. ๐ฏ For example, this could be the minimum of a set of RTT measurements taken over the previous 5 minutes. โฑ๏ธ
- There are cases where the current CWND doesn't reflect the path capacity ๐ At the end of Slow Start, the CWND can be way bigger than what's needed to fully use the path (a CWND overshoot, aka a total mess ๐). It's inappropriate to use that overshoot as the basis for estimating the capacity. In most cases the CWND will settle down to a stable value after several more RTTs. ๐ธ One mitigation during Slow Start could be setting the
saved_cwndbased on the validated pipe size (i.e., CWND / 2). ๐ง - When the sender is rate limited, or it's in the RTT right after a burst of transmission, it usually sends less data than the CWND allows. โจ Those observations could be discounted when estimating the
saved_cwnd(e.g., when a previous observation recorded a higher value). ๐
4.2. Confirming the Path in the Reconnaissance Phase ๐
in the Reconnaissance Phase, the sender opens a connection and starts sending initial data while measuring the current RTT. โณ The CC isn't modified here. ๐ซถ So the sender needs to limit the initial data, sent in the first RTT of transmitted data, to no more than the IW [RFC9002]. This transmission using the IW is assumed to be a safe starting point for any path, so it doesn't pile excessive load onto a potentially congested path. ๐
okay this next bit is super important ๐ซ Careful Resume does not permit multiple concurrent reuse of the saved CC parameters. When multiple new concurrent connections are made to a server, each one can have a valid saved_remote_endpoint, but the saved_cwnd can only be used by one connection at a time. ๐ค This stops the sender from doing multiple jumps in the CWND, each one based on the same saved_cwnd, which would create an excessive aggregate load at the bottleneck. ๐ฅ
how you stop that reuse depends on how your server is designed ๐ง For example, if a simple sender gets multiple connections from a Remote Endpoint, the sender process could use a hash table to manage the CC parameters. But with some types of load balancing, a distributed system might be needed to keep this invariant, because the load balancer hashes connections by 4-tuple. That means multiple connections from the same client device can land on different server processes ๐ซ See also Section 4.2.
a sender that is rate limited [RFC7661] sends too little data to validate transmission at a higher rate ๐ข Such a sender is allowed to stay in the Reconnaissance Phase and not move to the Unvalidated Phase until there's more data in the transmission buffer than the CC algorithm would normally permit. ๐
4.2.1. Confirming the Path ๐ค๏ธ
paths can change over time for lots of reasons ๐ That can make the previously observed CC parameters totally irrelevant. To help confirm the path, the sender compares the saved_rtt with each current RTT sample. ๐
if the current RTT sample is less than half of the saved_rtt, that's regarded as too small ๐ฉ It's an indicator of a path change. The factor of two is there because jump_cwnd is calculated as half the measured saved_cwnd, and the sending rate ought not to exceed the rate observed when the saved_cwnd was measured. ๐งฎ
if the current RTT is larger than the saved_rtt, that results in a proportionally lower rate for the unvalidated packets, because the transmission is paced based on the current RTT. ๐ So this rate is still safe โ
If the current RTT was incorrectly measured as larger than the actual path RTT, the sender will receive an ACK for an unvalidated packet before it has finished the Unvalidated Phase. That ACK resets the CWND to reflect the flight_size, and then the sender enters the Validating Phase. The flight_size reflects the amount of outstanding data in the network, not the maximum that the CWND would allow. ๐ฆ
a current RTT that is more than ten times the saved_rtt is a sign of a path change ๐จ The value of ten covers both the latency increases from buffering on a path and any variation between RTT samples. ๐ซง
Note 1: In the Reconnaissance Phase, the sender calculates a minimum RTT over the phase and checks it on entry to the Unvalidated Phase. That way it doesn't need to check after every current RTT sample. ๐ง
Note 2: During the Unvalidated Phase, the minimum RTT cannot increase, so the minimum RTT can never be larger than (saved_rtt x 10) during the Unvalidated Phase. ๐
the sender also checks that the initial data was acknowledged ๐ Any loss could be a sign of persistent congestion. If a sender in the Reconnaissance Phase detects congestion, it stops using Careful Resume and goes back to normal CC. ๐โโ๏ธ Some transport protocols implement CC mechanisms that infer potential congestion from an increase in the current RTT. Designs need to consider whether that kind of indication is a suitable trigger for stopping Careful Resume and reverting to normal CC. ๐ค
4.3. Safety in the Unvalidated Phase ๐ก๏ธ
this section looks at whether it's safe to use saved CC parameters to tentatively update the CWND ๐ The goal is to avoid starving other flows that could have started, or increased their use of capacity, since the capacity of the path was observed. ๐ฅบ
to avoid causing significant congestion for connections that have started using a shared bottleneck, a sender must not directly use the previous saved_cwnd to initialise a new flow, which would make it resume sending at the same rate. ๐ซ So the jump_cwnd is limited to half the previously saved_cwnd. ๐
4.3.1. Lifetime of CC Parameters โณ
using the previously observed parameters for the long term isn't appropriate ๐ โโ๏ธ A Lifetime defines how long a set of saved CC parameters can be safely reused. The maximum Lifetime is a configurable parameter for a sender. An implementation also needs a way to flush the set of saved CC parameters after a configuration change. ๐งน
[RFC9040] gives guidance on implementing TCP Control Block Interdependence, but it doesn't specify how long a saved parameter can safely be reused. ๐คทโโ๏ธ [RFC7661] specifies a method for managing an unvalidated CWND, and it says:
| After a fixed period of time (the non-validated period (NVP)), the
| sender adjusts the CWND (Section 4.4.3). The NVP SHOULD NOT
| exceed five minutes.
Section 5 of [RFC7661] discusses the rationale for choosing that period. ๐ However, [RFC7661] targets rate-limited connections using normal CC. Careful Resume includes extra mechanisms to avoid and mitigate the effects of overshoot, so a longer period can be justified when using a saved_cwnd with Careful Resume. ๐
when the path characteristics are known to be dynamic, or the path varies, a small Lifetime is desirable (e.g., measured in minutes) โก For stable paths, where the sender doesn't expect the path to be shared by many senders, a longer Lifetime (e.g., measured in hours) could be used ๐๏ธ A bottleneck shared by a large number of senders carries greater risk, because Careful Resume connections could contribute congestion that leads to prolonged overload with starvation ๐ฑ This can be mitigated by setting a small Lifetime. ๐ซถ
4.3.2. Pacing in the Unvalidated Phase ๐ต
a sender needs to avoid any step increase in the CWND that results in a burst of packets bigger than the size of the CC algorithm's IW ๐ โโ๏ธ This is consistent with [RFC8085] and [RFC9000].
pacing packets as a function of the current RTT, rather than the saved_rtt, adds extra safety during the Unvalidated Phase ๐ It stops a smaller saved_rtt from inflating the sending rate. The lower bound on the minimum acceptable current RTT keeps unvalidated packets from being sent at a rate higher than was previously observed. ๐งฑ
here's a relevant pacing rhythm example ๐ฅ An Inter-packet Transmission Time (ITT) is determined using the current Maximum Packet Size (MPS), including headers, the saved_cwnd, and the current RTT. A safety margin can be configured to avoid sending more than a maximum (max_jump):
jump_cwnd = Min(max_jump,saved_cwnd/2)
ITT = (current RTT x MPS)/jump_cwnd
this follows the idea presented in [RFC4782], [INIT-SPREADING], and [CONEXT15] ๐ Other sender mitigations have also been suggested to avoid line-rate bursts (e.g., [TCP-SSR]). ๐
4.3.3. Exit from the Unvalidated Phase Because of Variable Network Conditions ๐ข
- Careful Resume is designed to be robust to changes in network conditions caused by variations in the forwarding path (see Section 1.5), such as equipment reconfiguration or changes in link conditions. โ๏ธ Path confirmation is what mitigates this. โ
- Careful Resume is also designed to be robust to changes in network traffic, including new flows arriving that compete for capacity at a shared bottleneck ๐ฆ This is mitigated by jumping to no more than half of the
saved_cwnd, and by pacing. ๐ซถ - Careful Resume is designed to avoid unduly suppressing flows that have used the capacity since it was observed ๐ฆ This is further mitigated by bounding the duration of the Unvalidated Phase and the following Validating Phase, plus the conservative design of the Safe Retreat Phase. ๐
4.4. The Validating Phase ๐
okay so the Validating Phase has one job: if the capacity turns out to be not validated, it sends you straight into the Safe Retreat Phase ๐จ That's its whole purpose.
When the sender finishes the Unvalidated Phase, it stops using the unvalidated CWND ๐
. That happens after sending a jump_cwnd worth of data, after one RTT, or after an acknowledgment for an unvalidated packet arrives, whichever comes first.
Then: if flight_size was less than or equal to PipeSize, the sender sets CWND to PipeSize and stops using Careful Resume โจ. Otherwise, if CWND is bigger than flight_size, it gets shrunk down to flight_size. After that the sender just waits for ACKs to prove the capacity is real ๐
New packets get sent when previously sent data is newly acknowledged. CWND grows during the Validating Phase based on the ACKs it receives. That lets new data flow, but it has no lasting effect on CWND if congestion shows up later ๐ฆ
4.5. Safety in the Safe Retreat Phase ๐
This section is all about staying safe once congestion has been detected for unvalidated packets ๐ฌ
The Safe Retreat Phase sets a safe CWND value so the unvalidated packets drain out of the path. That happens after a packet loss is detected, or when ACKs show the sent packets were marked as ECN-CE. The CC parameters that were used are now invalid, so they get removed ๐งน
The Safe Retreat reaction is different from a traditional reaction to detected congestion, because a jump_cwnd can lead to a rate way higher than Slow Start would ever allow ๐ณ That jump could aggressively feed a congested bottleneck, causing overshoot where a disproportionate number of packets from existing flows get knocked out of the buffer there ๐ So a sender in the Safe Retreat Phase needs to respond to detected congestion by reducing CWND significantly below saved_cwnd ๐
During loss recovery, a receiver can cumulatively acknowledge data that was sent in the Unvalidated Phase, as well as acknowledge the successful retransmission of data. [RFC3465] explains how to account for those ACKs properly ๐ The sender tracks received ACKs that confirm the unvalidated packets arrived, so it can measure the maximum available capacity, called the "PipeSize" ๐ (The first unvalidated packet can be found by recording the sequence number of the first packet sent in the Unvalidated Phase.) This PipeSize is used later to reset ssthresh. But heads up: it is not a safe measure of the currently available share of capacity whenever there was also a significant overshoot at the bottleneck, so it must not be used to reinitialise CWND โ ๏ธ
Proportional Rate Reduction (PRR) [RFC9937] assumes that it is safe to reduce the rate gradually during congestion avoidance. So PRR isn't the right fit when there might be significant overshoot in the use of capacity, which can be the case when the Safe Retreat Phase is entered ๐
How recovery from loss works depends on the design of the transport protocol ๐งฉ A TCP or SCTP sender is required to retransmit all lost data [RFC5681]. For some transports (e.g., QUIC and DCCP), the need for loss recovery depends on the sender's retransmission policy. On entry to the Safe Retreat Phase, CWND can be significantly reduced. If there were multiple losses, a sender recovering all lost data could then take multiple RTTs to finish ๐ข
4.6. Returning to Normal Congestion Control ๐ก
After using Careful Resume, the CC controller returns to using normal CC ๐ธ
The CWND at entry to this phase will have been increased when a sender passed through the Unvalidated Phase, unless the sender was rate limited. In that case CWND gets reset based on the used capacity ๐ CWND is not reduced below the IW, unless congestion was detected. However, note that in some cases the value of CWND could be significantly lower than jump_cwnd (e.g., when a sender didn't utilise the entire CWND in the Unvalidated Phase) ๐ค How each CC algorithm implements this depends on that algorithm's design.
Once a sender is no longer using Careful Resume, it's permitted to start observing the capacity of the path ๐๐
4.7. Limitations from Transport Protocols ๐ง
CWND is one factor that limits a sender's sending rate, but it's not the only one. Other mechanisms can also constrain the maximum sending rate of a transport protocol ๐ค A transport protocol might need to update these mechanisms to fully utilise the CWND made available by Careful Resume:
- A TCP sender is limited by the receiver window (
rwnd). Unless it's configured at a receiver,rwndconstrains the rate of increase for a connection and reduces the benefit of Careful Resume. - QUIC includes flow control mechanisms and mechanisms to prevent amplification attacks. In particular, a QUIC receiver might need to issue proactive
MAX_DATAframes to increase the flow control limits of a connection that is started when using Careful Resume, so it gets the expected benefit ๐
5. Operational Considerations ๐ ๏ธ
This section provides some operational considerations for network providers ๐ผ As noted above, using CC parameters that were observed during a previous connection is inherently a tradeoff: there are potential performance gains for the new connection, and risks of degraded performance for other connections that share a common bottleneck โ๏ธ A transport endpoint often has no visibility of changes in the level of network traffic, nor of the forwarding path the transport path runs over. So Careful Resume is a sender-side transport change that has been designed so any potential "harm" to other flows is constrained ๐ก๏ธ It seeks to detect whether the transport path has changed since that capacity was observed. Importantly, whenever a sender detects that assumptions about the capacity are not valid, the sender safely responds to reduce the impact on other flows (see Section 1.5) ๐ซถ
There are three ways that the use of Careful Resume can be constrained:
- The maximum configured jump window (
max_jump) (see Section 3.3), - The Remote Endpoint identifying the client and the server that are permitted to use a specific set of saved CC parameters (see Section 2.2),
- The configured Lifetime for a set of saved CC parameters (see Section 4.3.1).
Network methods such as Equal Cost Multipath Routing, Anycast Routing, and Network Address Translation can result in changes to the forwarding path ๐ The impact of these methods on Careful Resume can be minimised when the network is configured so that the alternative paths are provisioned to support equivalent capacity (i.e., a change to the forwarding path does not introduce a significant reduction in the capacity of the smallest bottleneck on the end-to-end path) ๐
For many network paths, the smallest bottleneck is located in the access part of the end-to-end path ๐ As an example, consider a typical client on an access network that could connect to a remote server, with a capacity bottleneck located in the access part of this path. When the client connects to a server using an anycast destination address, the anycast routing would be configured to distribute connections to a corresponding server. A client would then be unaware of whether different instances of the client's connections (with the same address pair) would terminate at the same or different servers, or at servers located at different "server farms" ๐ Hence, if a server is configured to send using Careful Resume, there is an onus to appropriately manage the use of saved CC parameters (see Section 4.2) ๐ง
The way this is realised depends on the design choices in configuring the network and the servers ๐๏ธ On the one hand, if all the servers responding to a given IP address share the same location (e.g., are in the same data center), then a method could be provided to coordinate their sharing of the CC parameters that are used to send data using Careful Resume ๐ค On the other hand, if the service configuration is such that subsequent use of the IP anycast address might result in a very different path to a server (e.g., at a different location where the path would be unable to support the same capacity), a sender should not use Careful Resume based on saved CC parameters ๐ โโ๏ธ
6. IANA Considerations ๐ญ
This document has no IANA actions ๐ท
7. Security Considerations ๐
Security is a big deal here, bestie ๐ค The security considerations are the same as for other sender-based CC methods. Those methods all rely on the receiver appropriately acknowledging receipt of data ๐จ Whether an on-path or off-path attacker can influence CC depends on the security properties of the transport protocol being used. Take this seriously ๐จ
8. References ๐
8.1. Normative References
[RFC2119] Bradner, S., "Key words for use in RFCs to Indicate
Requirement Levels", BCP 14, RFC 2119,
DOI 10.17487/RFC2119, March 1997,
<https://www.rfc-editor.org/info/rfc2119>.
[RFC2914] Floyd, S., "Congestion Control Principles", BCP 41,
RFC 2914, DOI 10.17487/RFC2914, September 2000,
<https://www.rfc-editor.org/info/rfc2914>.
[RFC8085] Eggert, L., Fairhurst, G., and G. Shepherd, "UDP Usage
Guidelines", BCP 145, RFC 8085, DOI 10.17487/RFC8085,
March 2017, <https://www.rfc-editor.org/info/rfc8085>.
[RFC8174] Leiba, B., "Ambiguity of Uppercase vs Lowercase in RFC
2119 Key Words", BCP 14, RFC 8174, DOI 10.17487/RFC8174,
May 2017, <https://www.rfc-editor.org/info/rfc8174>.
8.2. Informative References ๐โจ
okay so these are the informative references, aka the background reading list ๐ค Each one is listed with all its details, so you can go find it yourself. The URLs are in code so nothing gets mangled ๐
[BBR-CC] Cardwell, N., Swett, I., and J. Beshay, "BBR Congestion Control", Work in Progress, Internet-Draft, draft-ietf-ccwg-bbr-05, 2 March 2026, https://datatracker.ietf.org/doc/html/draft-ietf-ccwg-bbr-05.
[CONEXT15] Li, Q., Dong, M., and P. B. Godfrey, "Halfback: Running Short Flows Quickly and Safely", CoNEXT '15: Proceedings of the 11th ACM Conference on Emerging Networking Experiments and Technologies, DOI 10.1145/2716281.2836107, 2015, https://doi.org/10.1145/2716281.2836107.
[CR25] Yanev, M., Custura, A., Secchi, R., and G. Fairhurst, "Analysis of Careful Resumption of Internet Congestion Control from Retained Path State", Computer Networks, vol. 276, DOI 10.1016/j.comnet.2025.111950, 2026, https://www.sciencedirect.com/science/article/abs/pii/S1389128625009156.
[IJSCN] Thomas, L., Dubois, E., Kuhn, N., and E. Lochin, "Google QUIC performance over a public SATCOM access", International Journal of Satellite Communications and Networking, vol. 37, no. 6, pp. 601-611, DOI 10.1002/sat.1301, 2019, https://doi.org/10.1002/sat.1301.
[INIT-SPREADING] Sallantin, R., Baudoin, C., Arnal, F., Dubois, E., Chaput, E., and A. Beylot, "Safe increase of the TCP's Initial Window Using Initial Spreading", Work in Progress, Internet-Draft, draft-irtf-iccrg-sallantin-initial-spreading-00, 15 January 2014, https://datatracker.ietf.org/doc/html/draft-irtf-iccrg-sallantin-initial-spreading-00.
[LOG] Custura, A. and G. Fairhurst, "Quic Logging for Convergence of Congestion Control from Retained State", Work in Progress, Internet-Draft, draft-ietf-tsvwg-careful-resume-qlog-02, 2 February 2026, https://datatracker.ietf.org/doc/html/draft-ietf-tsvwg-careful-resume-qlog-02.
[MAPRG111] Kuhn, N., Stephan, E., Fairhurst, G., Jones, T., and C. Huitema, "Feedback from using QUIC's 0-RTT-BDP extension over SATCOM public access", IETF 111 Proceedings, July 2021, https://www.ietf.org/proceedings/111/slides/slides-111-maprg-feedback-from-using-quics-0-rtt-bdp-extension-over-satcom-public-access-00.pdf.
[RFC3465] Allman, M., "TCP Congestion Control with Appropriate Byte Counting (ABC)", RFC 3465, DOI 10.17487/RFC3465, February 2003, https://www.rfc-editor.org/info/rfc3465.
[RFC4782] Floyd, S., Allman, M., Jain, A., and P. Sarolahti, "Quick-Start for TCP and IP", RFC 4782, DOI 10.17487/RFC4782, January 2007, https://www.rfc-editor.org/info/rfc4782.
[RFC5681] Allman, M., Paxson, V., and E. Blanton, "TCP Congestion Control", RFC 5681, DOI 10.17487/RFC5681, September 2009, https://www.rfc-editor.org/info/rfc5681.
[RFC5783] Welzl, M. and W. Eddy, "Congestion Control in the RFC Series", RFC 5783, DOI 10.17487/RFC5783, February 2010, https://www.rfc-editor.org/info/rfc5783.
[RFC6675] Blanton, E., Allman, M., Wang, L., Jarvinen, I., Kojo, M., and Y. Nishida, "A Conservative Loss Recovery Algorithm Based on Selective Acknowledgment (SACK) for TCP", RFC 6675, DOI 10.17487/RFC6675, August 2012, https://www.rfc-editor.org/info/rfc6675.
[RFC6928] Chu, J., Dukkipati, N., Cheng, Y., and M. Mathis, "Increasing TCP's Initial Window", RFC 6928, DOI 10.17487/RFC6928, April 2013, https://www.rfc-editor.org/info/rfc6928.
[RFC7661] Fairhurst, G., Sathiaseelan, A., and R. Secchi, "Updating TCP to Support Rate-Limited Traffic", RFC 7661, DOI 10.17487/RFC7661, October 2015, https://www.rfc-editor.org/info/rfc7661.
[RFC9000] Iyengar, J., Ed. and M. Thomson, Ed., "QUIC: A UDP-Based Multiplexed and Secure Transport", RFC 9000, DOI 10.17487/RFC9000, May 2021, https://www.rfc-editor.org/info/rfc9000.
[RFC9002] Iyengar, J., Ed. and I. Swett, Ed., "QUIC Loss Detection and Congestion Control", RFC 9002, DOI 10.17487/RFC9002, May 2021, https://www.rfc-editor.org/info/rfc9002.
[RFC9040] Touch, J., Welzl, M., and S. Islam, "TCP Control Block Interdependence", RFC 9040, DOI 10.17487/RFC9040, July 2021, https://www.rfc-editor.org/info/rfc9040.
[RFC9293] Eddy, W., Ed., "Transmission Control Protocol (TCP)", STD 7, RFC 9293, DOI 10.17487/RFC9293, August 2022, https://www.rfc-editor.org/info/rfc9293.
[RFC9406] Balasubramanian, P., Huang, Y., and M. Olson, "HyStart++: Modified Slow Start for TCP", RFC 9406, DOI 10.17487/RFC9406, May 2023, https://www.rfc-editor.org/info/rfc9406.
[RFC9438] Xu, L., Ha, S., Rhee, I., Goel, V., and L. Eggert, Ed., "CUBIC for Fast and Long-Distance Networks", RFC 9438, DOI 10.17487/RFC9438, August 2023, https://www.rfc-editor.org/info/rfc9438.
[RFC9937] Mathis, M., Cardwell, N., Cheng, Y., and N. Dukkipati, "Proportional Rate Reduction (PRR)", RFC 9937, DOI 10.17487/RFC9937, December 2025, https://www.rfc-editor.org/info/rfc9937.
[TCP-SSR] Hughes, A., Touch, J., and J. Heidemann, "Issues in TCP Slow-Start Restart After Idle", Work in Progress, Internet-Draft, draft-hughes-restart-00, December 2001, https://datatracker.ietf.org/doc/html/draft-hughes-restart-00.
Appendix A. Notes on the Careful Resume Phases ๐ง
okay this bit is the cheat sheet ๐ The table below shows how Careful Resume works step by step. It's informative, so for the real normative rules you go back to the body of the document ๐ซถ The description is based on a normal CC that uses Reno, and the PipeSize tracks the validated CWND โจ
The phases in Table 1 line up with Sections 3.2 through 3.5. The table also uses these abbreviations:
SS = Slow Start
FS = flight_size
PS = PipeSize
ACK = highest acknowledged packet
CC = Congestion Control
CR = Careful Resume
IW = Initial congestion Window
CWND = Congestion Window
+=======+=========+============+============+===========+===========+
|Phase |Normal |Recon. |Unvalidated |Validating |Safe Ret. |
+=======+=========+============+============+===========+===========+
| |Observing|Confirm path|Send faster |Validate |Drain path;|
| |CC params| |using |new CWND; |Update PS |
| | | |saved_cwnd |Update PS | |
+-------+---------+------------+------------+-----------+-----------+
|On | - |CWND=IW |PS=FS |If (FS>PS) |CWND=(PS/2)|
|entry: | | |jump_cwnd |{CWND=FS} | |
| | | |=saved_cwnd |else | |
| | | |/2; CWND |{CWND=PS; | |
| | | |=jump_cwnd |use Normal | |
| | | | |CC} | |
+-------+---------+------------+------------+-----------+-----------+
|CWND: |When in |CWND |CWND is not |CWND can |CWND is not|
| |observe, |increases |increased |increase |increased |
| |measure |using SS | |using | |
| |saved | | |normal CC | |
| |_cwnd | | | | |
+-------+---------+------------+------------+-----------+-----------+
|PS: | - | - |PS+=ACKed |
+-------+---------+------------+------------+-----------+-----------+
|RTT: |Measure |Measure | - | - | - |
| |saved_rtt|current RTT | | | |
+-------+---------+------------+------------+-----------+-----------+
|If loss|Normal CC|Normal CC; |Enter Safe Retreat | - |
|or ECN-| |CR is not | | |
|CE: | |allowed | | |
+-------+---------+------------+------------+-----------+-----------+
|Next |Observing|If (CWND, |If (FS>CWND |If (ACK >= |If (ACK >= |
|Phase: |(as |Lifetime, |or >1 RTT |last |last |
| |needed) |and RTT |has passed |unvalidated|unvalidated|
| | |confirmed), |or ACK >= |packet), |packet), |
| | |enter |first |use Normal |ssthresh = |
| | |Unvalidated;|unvalidated |CC |PS x Beta; |
| | |else |packet), If | |and use |
| | |CWND=Max |((FS>CWND) | |Normal CC |
| | |(PS,IW); and|or | | |
| | |use Normal |(FS<=PS)) | | |
| | |CC |cwnd=PS; | | |
| | | |and use | | |
| | | |Normal CC | | |
| | | |else | | |
| | | |cwnd=FS; | | |
| | | |enter | | |
| | | |Validating | | |
+-------+---------+------------+------------+-----------+-----------+
Table 1: Illustration of the Operation of Careful Resume
Appendix B. Examples of the Careful Resume Phases ๐
these examples are the worked-out version ๐ They consider an implementation that keeps track of transmitted data in terms of packets, and they give informative examples of use ๐
In the Unvalidated Phase, the first unvalidated packet is the highest sent packet recorded on entry to this phase. In the Validating Phase and Safe Retreat Phase, the sender tracks the last unvalidated packet, which is also the highest sent packet number recorded on entry to this phase. The PipeSize (PS) tracks the validated portion of the CWND. The PS is set to the CWND on entry to the Unvalidated Phase, and it gets updated after receiving an ACK for each additional packet. The default value of Beta is 0.5 ๐ธ
Note: To simplify the description, these examples are described using packet numbers (whereas QLOG variables are expressed in bytes). ๐
B.1. Example with No Loss โจ
okay so the first example is the no-loss glow-up ๐ The sender starts by sending IW packets, which we're assuming is 10 packets, during the Reconnaissance Phase. Then, in the next RTT, it keeps sending more until it becomes CWND limited (aka flight_size = CWND) ๐ฅ
The sender in the Reconnaissance Phase then confirms the RTT and the other conditions for using Careful Resume. In this example, that gets confirmed once the sender has 29 packets in flight ๐
Then the sender enters the Unvalidated Phase! ๐ฆ (This path confirmation could have happened earlier if there had been data available to send.) The sender sets PipeSize to the flight_size (29 packets here) and then sets CWND to 150 packets, which is based on half of the previously observed saved_cwnd of 300 packets ๐
Now the sender sends 121 unvalidated packets, which is the unused portion of the current CWND. Every time a packet is sent, the sender checks whether 1 RTT has passed since entering the Unvalidated Phase. If it has not, the Validating Phase gets entered instead. This check only triggers for cases where the sender is rate limited, as shown in the following example: PipeSize increases after each ACK is received ๐ธ
When the first unvalidated packet gets acknowledged (packet number 30), the sender enters the Validating Phase. (This transition would also happen if flight_size increased to equal CWND.) During this phase, CWND can be increased for each ACK that acknowledges an unvalidated packet, because that tells us the packet was validated โจ
When an ACK comes in that acknowledges the last packet that was sent in the Unvalidated Phase, the sender stops using Careful Resume. For example, if CWND is less than ssthresh, a Reno or CUBIC sender using normal CC is permitted to use Slow Start to grow CWND toward ssthresh, and then it will enter congestion avoidance ๐ง
B.2. Example with No Loss, Rate Limited ๐
A rate-limited sender will not fully use the available CWND when it uses Careful Resume, so CWND gets reset on entry to the Validating Phase, as described below ๐
The sender starts by sending up to IW packets (10) in the Reconnaissance Phase. It goes through everything like the first example, transitions to the Unvalidated Phase, where CWND is set to 150 packets, and PipeSize is set to the flight_size (that's 29 packets).
Then the sender becomes rate limited, because the example only sends 50 unvalidated packets ๐ญ
After about one RTT (for example, by comparing the current time with local timestamps for each sent packet, or by receiving an ACK for the first unvalidated packet), the sender still has not fully used the CWND. So it enters the Validating Phase and resets CWND to the current flight_size (50 packets). During this phase, CWND can be increased for each received ACK that validates reception of an unvalidated packet. PipeSize also increases with each ACK received, to reflect the capacity that was discovered ๐
The sender finishes using Careful Resume when a received ACK acknowledges the last packet that was sent in the Unvalidated Phase. Then it stops using Careful Resume, just like in the no-loss example ๐
B.3. Example with Loss Detected in the Reconnaissance Phase ๐
When a sender detects that a packet was lost in the Reconnaissance Phase, it stops using Careful Resume and recovers the loss with the normal loss recovery algorithm and normal CC. The sender may have discovered a capacity limit, so it is not allowed to keep using Careful Resume. In this case there is no change to the CC algorithm, and CWND is the same as if Careful Resume had never been attempted ๐ซถ
B.4. Example with Loss Detected in the Validating Phase ๐
Same as the first example, the sender enters the Unvalidated Phase with a CWND of 150 packets, and with PipeSize initialised to the flight_size (29 packets) ๐
The sender now sends 121 unvalidated packets, which uses up the remaining unused CWND. This example looks at what happens when one of the unvalidated packets gets lost. We assume that the lost packet is 64 (the 35th packet sent in the Unvalidated Phase) ๐ฌ
The received ACKs acknowledge the first 34 unvalidated packets. At this point PipeSize is equal to 63 (29 + 34) packets.
A loss is then detected (by a timer, or by receiving three ACKs that do not acknowledge packet number 35). The sender then enters the Safe Retreat Phase, because CWND was not validated. Assuming that IW was 10 packets, CWND is reset to Max(10,PS/2) = Max(10,63/2) = 31 packets. This CWND is used during the Safe Retreat Phase, because congestion was detected and the sender still doesn't know whether the remaining unvalidated packets will be successfully acknowledged. This conservative calculation makes sure the sender drains the path after this potentially severe congestion event. There is no further increase in CWND during this phase ๐งผ
The sender keeps receiving ACKs that acknowledge the remaining 86 (121-35) unvalidated packets. Remember that the 35th unvalidated packet was lost and had packet number 64 (29+35). PipeSize tracks the capacity discovered by the ACKs that acknowledge the unvalidated packets (in other words, PipeSize increases for each received ACK that acknowledges new data). Even though this PipeSize can't be used to safely initialise CWND (because it was measured when the sender had aggressively created overload), the estimated PipeSize (which in this case is 121-1 = 120 packets) can be used to set ssthresh on exit from Safe Retreat, since it does indicate a measured upper limit to the current capacity ๐ฅ
Once all the unvalidated packets sent in the Unvalidated Phase have either been acknowledged or declared lost, the sender updates ssthresh to be no larger than the recently measured PipeSize multiplied by Beta (the final action of the Safe Retreat Phase), and the sender stops using Careful Resume. Because CWND will now be less than ssthresh, a sender using normal CC is permitted to use Slow Start to grow CWND toward ssthresh, after which it will enter congestion avoidance ๐
Appendix C. Implementation Notes for Using BBR ๐
Bottleneck Bandwidth and Round-trip propagation time (BBR) uses recent measurements of a transport connection's delivery rate, Round Trip Time (RTT), and packet loss rate to build an explicit model of the network path. BBR then uses that model to control both how fast it sends data and the maximum volume of data it allows in flight in the network at any time [BBR-CC] ๐ง
When the flow is controlled using BBR, Careful Resume is implemented by setting the pacing rate from the saved CC parameters, with the following precautions:
- The flag
carefully-resumingis added to the BBR state to indicate that the sender is allowed to send unvalidated packets. It is initialised to False when a BBR flow starts. - The prerequisites for using Careful Resume are described in Section 3.2.
C.1. Sending Unvalidated Packets Using BBR ๐
Careful Resume is allowed to transmit unvalidated packets only when the BBR flow is in the Startup state ๐
The probing rate is configured to 1/2 of the bottleneck bandwidth, derived from the CWND calculation specified in the saved CC parameters, following the requirements in Section 3.3 โจ
The sender starts the Unvalidated Phase at the beginning of a BBR round, and sets the carefully-resuming flag to True. When this flag is set, the BBR congestion controller sets the BBR pacing rate to the larger of the nominal pacing rate (BBR.bw multiplied by BBRStartupPacingGain) or the calculated probing rate. Then CWND is set to the larger of BBR.bw and the probing rate, multiplied by BBR.rtt_min times BBRStartupCwndGain ๐
The carefully-resuming flag is reset to False two rounds after it is set (in other words, after all the packets sent in the first round of "carefully resuming" have been received and acknowledged by the peer). At that stage, once the capacity has been validated, the measured delivery rate is expected to reflect the probing rate ๐ฆ
If congestion is detected while the carefully-resuming flag is True, BBR exits the Startup state and enters the Drain state (implementing the Safe Retreat Phase) ๐จ
C.2. Validation for BBR ๐
When using BBR, the Validation Phase is realised using the BBR rules for exiting Startup. Upon exiting Startup, the connection estimates that the measured delivery rate will reflect the flow's share of the actual bottleneck bandwidth. If congestion is detected while using Careful Resume (i.e., the carefully-resuming flag is True), BBR then exits the Startup state and enters the Drain state ๐ธ
C.3. Safe Retreat for BBR ๐
When using BBR, the Safe Retreat Phase is entered if the Drain state is entered while the carefully-resuming flag (see Appendix C) is still True (in other words, if less than 2 full rounds have elapsed after the sender entered the Unvalidated Phase). The delivery rates measured in these conditions are tainted, because packets sent during the attempt are still queued at the bottleneck buffer and could have "pushed out" packets belonging to any competing flows. Therefore, any delivery rates measured in the Drain state MUST be discarded if the carefully-resuming flag is set to True. This flag is cleared upon exiting the Drain state ๐งน
Acknowledgments ๐
The authors would like to thank John Border, Gabriel Montenegro, Patrick McManus, Ian Swett, Igor Lubashev, Robin Marx, Roland Bless, Franklin Simo, Kazuho Oku, Tong, Ana Custura, Neal Cardwell, Marten Seemann, Matthias Hofstaetter, Nicolai Fischer, Yi Huang, Mihail Yanev, and Joerg Deutschmann for their fruitful comments in developing this specification. They also thank Mike Bishop for his careful suggestions on the structure used to describe the phases. Thanks also to Mohamed Boucadair and to Dan Harkins for his secdir review ๐ซถ
The authors would like to thank Tom Jones for co-authoring previous draft versions of this document ๐
Authors' Addresses ๐
Nicolas Kuhn
Thales Alenia Space
Email: nicolas.kuhn.ietf@gmail.com
Emile Stephan
Orange
Email: emile.stephan@orange.com
Godred Fairhurst
University of Aberdeen
School of Engineering
Fraser Noble Building
Aberdeen
AB24 3UE
United Kingdom
Email: gorry@erg.abdn.ac.uk
Raffaello Secchi
University of Aberdeen
School of Engineering
Fraser Noble Building
Aberdeen
AB24 3UE
United Kingdom
Email: r.secchi@abdn.ac.uk
Christian Huitema
Private Octopus Inc.
Email: huitema@huitema.net
๐ฆ where this page comes from
- ietf: rfc9959 2026-05
- ๐ girlified by claude-haiku-5-5 on : a language model's rewrite of the original, under its terms