On Windows Azure everything including bandwidth has a price tag, but don’t be alarmed. The price tag isn’t that steep.
The important thing to remember on the cloud, is that we’re talking about economies of scale. This also means, that the cost of operation grows along with the scale and reach of your application.
Setting Cache-Control on publicly accessible Windows Azure Blobs can help reduce bandwidth by preventing consumers from having to continuously download resources. Additionally, it will greatly contribute to creating a more responsive end-user experience.
Cache-Control allows you to specify a relative amount of time to cache data after it was received. It’s mostly recommended when you need control over how caching is done.
Data Transfers Pricing Details For Windows Azure (August 2013)
|OUTBOUND DATA TRANSFERS||ZONE 1||ZONE 2|
|First 5 GB / Month||Free||Free|
|5 GB – 10 TB 1 / Month||$0.12 per GB||$0.19 per GB|
|Next 40 TB / Month||$0.09 per GB||$0.15 per GB|
|Next 100 TB / Month||$0.07 per GB||$0.13 per GB|
|Next 350 TB / Month||$0.05 per GB||$0.12 per GB|
max-age=[seconds] — specifies the maximum amount of time that a representation will be considered fresh. Similar to
Expires, this directive is relative to the time of the request, rather than absolute. [seconds] is the number of seconds from the time of the request you wish the representation to be fresh for.
s-maxage=[seconds] — similar to
max-age, except that it only applies to shared (e.g., proxy) caches.
public — marks authenticated responses as cacheable; normally, if HTTP authentication is required, responses are automatically private.
private — allows caches that are specific to one user (e.g., in a browser) to store the response; shared caches (e.g., in a proxy) may not.
no-cache — forces caches to submit the request to the origin server for validation before releasing a cached copy, every time. This is useful to assure that authentication is respected (in combination with public), or to maintain rigid freshness, without sacrificing all of the benefits of caching.
no-store — instructs caches not to keep a copy of the representation under any conditions.
must-revalidate — tells caches that they must obey any freshness information you give them about a representation. HTTP allows caches to serve stale representations under special conditions; by specifying this header, you’re telling the cache that you want it to strictly follow your rules.
proxy-revalidate — similar to
must-revalidate, except that it only applies to proxy caches.
Setting Cache-Control on Windows Azure Blobs
To set the Cache-Control on a blob you will need to get a blob reference (CloudBlockBlob) and set the CacheControl property found in the blob’s Properties. Then call the SetProperties method to persist the new
The following code uses the Windows Azure SDK 2.1 to creates a Container. Then it creates a Block Blob and uploads a short HTML document. Once the blob exists on Windows Azure Blob Storage, it sets the Cache-Control.
var blob = MakeCloudBlockBlob();
var htmlStream = MakeHtmlStream();
var cacheControl = "max-age=3600, must-revalidate";
blob.Properties.CacheControl = cacheControl;
private static CloudBlockBlob MakeCloudBlockBlob()
var connectionString = "DefaultEndpointsProtocol=https;AccountName=<account>;AccountKey=<key>";
var account = CloudStorageAccount.Parse(connectionString);
var client = account.CreateCloudBlobClient();
var container = client.GetContainerReference("blobs");
var blob = container.GetBlockBlobReference("test.html");
private static MemoryStream MakeHtmlStream()
var htmlStream = new MemoryStream();
htmlStream.Position = 0;
private static void WriteToStream(MemoryStream htmlStream)
var writer = new StreamWriter(htmlStream);
writer.Write("<html><body>this is a test</body></html>");
The code will generate a Blob with the following properties.
The following is an HTTP Trace of a subsequent request for the blob. This request results in a HTTP Status Code 304 Not Modified. This effectively confirms that the resource is taken from the client’s local cache and that it is not downloaded from the server. Consequently, greatly enhancing the end-user’s experience by reducing the amount of bandwidth necessary to satisfy the consumers needs.
If the client has performed a conditional GET request and access is allowed, but the document has not been modified, the server SHOULD respond with this status code. The 304 response MUST NOT contain a message-body, and thus is always terminated by the first empty line after the header fields.