dont-revalidate Cache-Control header

Ben Maurer <> Thu, 09 July 2015 22:29 UTC

Return-Path: <>
Received: from localhost ( []) by (Postfix) with ESMTP id 3324D1A1B44 for <>; Thu, 9 Jul 2015 15:29:15 -0700 (PDT)
X-Virus-Scanned: amavisd-new at
X-Spam-Flag: NO
X-Spam-Score: -4.311
X-Spam-Status: No, score=-4.311 tagged_above=-999 required=5 tests=[BAYES_50=0.8, DKIM_SIGNED=0.1, DKIM_VALID=-0.1, DKIM_VALID_AU=-0.1, HTML_MESSAGE=0.001, RCVD_IN_DNSWL_HI=-5, SPF_HELO_PASS=-0.001, SPF_PASS=-0.001, T_RP_MATCHES_RCVD=-0.01] autolearn=ham
Received: from ([]) by localhost ( []) (amavisd-new, port 10024) with ESMTP id z_kg5iLqFhgY for <>; Thu, 9 Jul 2015 15:29:12 -0700 (PDT)
Received: from ( []) (using TLSv1.2 with cipher DHE-RSA-AES128-SHA (128/128 bits)) (No client certificate requested) by (Postfix) with ESMTPS id CDB301A1B51 for <>; Thu, 9 Jul 2015 15:29:12 -0700 (PDT)
Received: from lists by with local (Exim 4.80) (envelope-from <>) id 1ZDKGQ-0004CU-7V for; Thu, 09 Jul 2015 22:25:54 +0000
Resent-Date: Thu, 09 Jul 2015 22:25:54 +0000
Resent-Message-Id: <>
Received: from ([]) by with esmtps (TLS1.2:DHE_RSA_AES_128_CBC_SHA1:128) (Exim 4.80) (envelope-from <>) id 1ZDKGL-0004Be-U5 for; Thu, 09 Jul 2015 22:25:49 +0000
Received: from ([]) by with esmtps (TLS1.2:RSA_ARCFOUR_SHA1:128) (Exim 4.80) (envelope-from <>) id 1ZDKGK-00069A-4a for; Thu, 09 Jul 2015 22:25:49 +0000
Received: by lbzd8 with SMTP id d8so37483105lbz.0 for <>; Thu, 09 Jul 2015 15:25:21 -0700 (PDT)
DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/relaxed;; s=20120113; h=mime-version:date:message-id:subject:from:to:content-type; bh=Hjp4cWvCq4Um6WHP91JYABvXYTrxTfZSfxPXEPdsTG4=; b=hGTdisCexAnJAik5/y7W8QKwexCZEGaxzvRrXREbno7COpntkakm8GOoaqo5YPQr8N h6mEBWrokcdnGaPLvPCEuqZHANS1Dwl1hyEE5ZzzSXN0KpEc+G3N6OWy/ZFdW4CMuOjF kLMYnUQ12NqTC0FzwVHa2JhrxFsUxlWC5V+e7jJQRHpVpqIAZ45WJWKyg1Fkxeg5wH+v wYeL2aGU9pBZtvhNKTlONlVow0KiIw2r8QWpJeuwByTUB1JGybqlYxvfZkaBZF3ITw+B g4MDcaeztOc3U9gRKjhpaw1iiK+qbke1maGBCDwtd9cNCtjfRK/5XuXD7seWIJyDt7Tq L4+A==
MIME-Version: 1.0
X-Received: by with SMTP id lm11mr16548840lac.41.1436480721023; Thu, 09 Jul 2015 15:25:21 -0700 (PDT)
Received: by with HTTP; Thu, 9 Jul 2015 15:25:20 -0700 (PDT)
Date: Thu, 09 Jul 2015 15:25:20 -0700
Message-ID: <>
From: Ben Maurer <>
To:, Ilya Grigorik <>
Content-Type: multipart/alternative; boundary="001a1133bdc61a77b3051a78bb8b"
Received-SPF: pass client-ip=;;
X-W3C-Hub-Spam-Status: No, score=-5.6
X-W3C-Hub-Spam-Report: AWL=-0.911, BAYES_00=-1.9, DKIM_SIGNED=0.1, DKIM_VALID=-0.1, DKIM_VALID_AU=-0.1, FREEMAIL_FROM=0.001, HTML_MESSAGE=0.001, RCVD_IN_DNSWL_LOW=-0.7, SPF_PASS=-0.001, W3C_AA=-1, W3C_WL=-1
X-W3C-Scan-Sig: 1ZDKGK-00069A-4a 07fe7badb0281e6d25c437236006b715
Subject: dont-revalidate Cache-Control header
Archived-At: <>
X-Mailing-List: <> archive/latest/29912
Precedence: list
List-Id: <>
List-Help: <>
List-Post: <>
List-Unsubscribe: <>

It is considered a best practice for websites to use "long caching" for
serving images, javascript and CSS. In long cacing if a website has a
resource X.js which might change from time to time, rather than referencing
X.js and giving the endpoint a short expiration date, they reference
X-v1.js with a nearly infinite expiration date. When X.js changes, the
website uploads X-v2.js and changes any references to use the new version.
This has the benefit that the browser never needs to revalidate resources
and that it sees changes instantly. [1]

At Facebook, we use this method to serve our static resources. However
we've noticed that despite our nearly infinite expiration dates we see
10-20% of requests (depending on browser) for static resource being
conditional revalidation. We believe this happens because UAs perform
revalidation of requests if a user refreshes the page. Our statistics show
that about 2% of navigations to FB are reloads -- however these requests
cause a disproportionate amount of traffic to our static resources because
they are never served by the user's cache.

A user who refreshes their Facebook page isn't looking for new versions of
our Javascript. Really they want updated content from our site. However UAs
refresh all subresoruces of a page when the user refreshes a web page. This
is designed to serve cases such as a weather site that says <img
src="/weather.php?zip=94025">. If that site had a 10 minute expiration on
the image, the user might be able to refresh the page and get more up to
date weather.

10-20% additional requests is a huge impact for a site's performance. When
a user presses refresh, they want to quickly see the latest updates on the
site they are on. Revalidating all resources on the site is a substantial
drain. In discussing this with Ilya Grigorik from the Chrome team, one
suggestion that came up was an explicit cache control option to tell UAs
not to revalidate. The proposed header would be Cache-Control:

This header would tell a UA that the resource in question is unquestionably
valid until it's expiration time. A UA MUST NOT send a conditional request
for a resource with a dont-revalidate header prior to the resource's
expiration. In most cases the UA SHOULD simply treat the resource as valid.
If the UA is not willing to treat the resource as valid, it should send a
full request with no revalidation. The UA MAY do this in cases where the
user has explicitly requested to use a clean cache -- for example a refresh
via ctrl+shift+r, or using developer tooling. Such functionality SHOULD be
targeted at advanced users rather than the average user.

Without an additional header, web sites are unable to control UA's behavior
when the user uses the refresh button. UA's are rightfully hesitant in any
solution that alters the long standing semantics of the refresh button (for
example, not refreshing subresources).