RFC 9959

Careful Resume: Convergence of Congestion Control from Retained State

๐Ÿ“… published May 2026, from ietf

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 (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:

  1. Information to confirm whether a saved path matches the current path.
  2. Information about the utilised path capacity and observed RTT, used to set CC parameters for the current connection.
  3. 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:

  1. 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) ๐Ÿ“Š;
  2. when a receiver has a local indication that a path/local interface has changed since the CC parameters were saved ๐Ÿ”Œ;
  3. when a receiver knows about the current hardware limitations ๐Ÿ–ฅ๏ธ;
  4. 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:

  1. 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 โœ…
  2. 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.
  3. 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 maximum jump_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 the saved_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 the saved_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 as rtt_not_validated in [LOG]) and returns to use normal CC. The reason this matters is that a sending rate calculated from a saved_cwnd depends 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 PipeSize gets set to the flight_size as 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_cwnd MUST be no more than half of the saved_cwnd. So jump_cwnd is less than or equal to Min(max_jump,(saved_cwnd/2)), and then CWND = 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 PipeSize goes 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_changed in [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_loss or ECN_CE in [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_size equals the CWND (for example, logged as last_unvalidated_packet_sent in [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_acknowledged in [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_exceeded in [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 PipeSize goes 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_loss or ECN_CE in [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_acknowledged in [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 PipeSize after it processes each ACK. The PipeSize gets 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_cwnd based 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, rwnd constrains 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_DATA frames 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-resuming is 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