title: Prevent Firefox from bypassing the disk caches in a request (how to disable "Race Cache With Network")?
body: <p>Since version 59, Firefox has a feature called Race Cache With Network (RCWN). If Firefox detects that the disk is slow, it can decide to start a network requests immediately without waiting for the cache. It is a trade-off: if the network requests wins the race, latency improved; if it the cache wins, network bandwidth has been wasted.</p>
  
  <p>It is a useful feature, but there is one scenario where it is undesirable. Assume a <a href="https://developer.mozilla.org/en-US/docs/Mozilla/Add-ons/WebExtensions/What_are_WebExtensions" rel="noreferrer">WebExtension</a> needs to update resources in the background (e.g. once per hour). Latency is not important here, although proper caching is crucial as you need to pay for outgoing traffic on the server side.</p>
  
  <p><strong>My question is how to disable RCWN on a request level.</strong> How can you create a request (through <a href="https://developer.mozilla.org/en-US/docs/Web/API/Fetch_API" rel="noreferrer"><code>fetch</code></a> or <a href="https://developer.mozilla.org/en-US/docs/Web/API/XMLHttpRequest" rel="noreferrer"><code>XMLHttpRequest</code></a>) that will always check the cache first and only then issue a network request. In other words, never race and never bypass the cache.</p>
  
  <p>I know that the feature can be turned off through configurations (<code>network.http.rcwn.enabled</code>), but that is not a solution. First, you would need to convince every user to flip that preference. Second, RCWN is a useful feature and it provides value during normal surfing where latency is important. Forcing users to disable it would lead to a suboptimal browsing experience.</p>
  
  <p>There is little documentation on RCWN expects these <a href="https://slides.com/valentingosu/race-cache-with-network-2017#/6" rel="noreferrer">slides</a>, but I found its implementation in the <a href="https://github.com/mozilla/gecko-dev/blob/615e78b5fc793fdadf7d13a8709c8da10feda14f/netwerk/protocol/http/nsHttpChannel.cpp#L4204" rel="noreferrer">Firefox source code</a>:</p>
  
  <pre><code>nsresult nsHttpChannel::OpenCacheEntryInternal(...) {
    ...
    if (sRCWNEnabled &amp;&amp; maybeRCWN &amp;&amp; !mApplicationCacheForWrite) {
      bool hasAltData = false;
      uint32_t sizeInKb = 0;
      rv = cacheStorage-&gt;GetCacheIndexEntryAttrs(openURI, extension, &amp;hasAltData,
                                                 &amp;sizeInKb);
  
      // We will attempt to race the network vs the cache if we've found
      // this entry in the cache index, and it has appropriate attributes
      // (doesn't have alt-data, and has a small size)
      if (NS_SUCCEEDED(rv) &amp;&amp; !hasAltData &amp;&amp;
          sizeInKb &lt; sRCWNSmallResourceSizeKB) {
        MaybeRaceCacheWithNetwork();
      }
    }
    ...
  }
  </code></pre>
  
  <p>I tried to understand the concept of "alt-data", but could not find any sources. To the best of my knowledge, it stands for alternative data. Could that be used (either by the server or through the client request) to force the cached data to be marked as alt-data, so racing will not occur?</p>
  
  <p>One other idea that I had: in a fetch request, clients can set <a href="https://developer.mozilla.org/de/docs/Web/HTTP/Headers/Cache-Control" rel="noreferrer"><code>Cache-Control: only-if-cached</code></a>, but that changes the semantic. It should stop races, but if there is no hit, it will return a stale result and not ask the server. Maybe that could be used to first try such a request and only then do a real network request. Not very elegant though. Is there some better solution to this problem?</p>
  
  <hr>
  
  <p>Notes: to get more information, Firefox allows to introspect the RCWN through <code>about:networking#rcwn</code>, and the cache through <code>about:cache</code>. If you check the RCWN, you can see that races are not too rare, even if you have an SSD. In the network monitor, raced requests will be marked in the transferred column, for example, as <code>100.86 KB (raced)</code>.</p>