Skip to content

Configure CDN Rules

⏱ 25 minutes advanced
📜Advancedcms

Default CDN settings work for most sites, but they are a compromise. Your marketing landing pages might benefit from aggressive caching, while your checkout flow needs no caching at all. Custom CDN rules let you fine-tune performance for each part of your site without sacrificing content freshness.


The CDN respects HTTP cache headers sent by your application. The most direct way to control caching is to set these headers in your code.

Add the response caching middleware and set cache profiles:

builder.Services.AddResponseCaching();
// In your middleware pipeline
app.UseResponseCaching();

Apply cache profiles to controllers or pages:

[ResponseCache(Duration = 600, VaryByHeader = "Accept-Language")]
public IActionResult Index()
{
return View();
}

For different cache behavior on different URL patterns, use middleware:

app.Use(async (context, next) =>
{
var path = context.Request.Path.Value;
if (path.StartsWith("/api/"))
{
context.Response.Headers["Cache-Control"] = "no-store";
}
else if (path.StartsWith("/static/"))
{
context.Response.Headers["Cache-Control"] = "public, max-age=31536000, immutable";
}
await next();
});

Optimizely CMS has a built-in output cache that works with the CDN layer. Configure it in your startup:

services.Configure<OutputCacheOptions>(options =>
{
options.DefaultExpiration = TimeSpan.FromMinutes(10);
});

Set different cache durations for different content types:

services.AddOutputCache(options =>
{
options.AddPolicy("LongCache", builder =>
builder.Expire(TimeSpan.FromHours(1)));
options.AddPolicy("ShortCache", builder =>
builder.Expire(TimeSpan.FromMinutes(2)));
});

Add custom headers for security, CORS, or debugging through middleware:

app.Use(async (context, next) =>
{
context.Response.Headers["X-Content-Type-Options"] = "nosniff";
context.Response.Headers["X-Frame-Options"] = "SAMEORIGIN";
context.Response.Headers["Strict-Transport-Security"] = "max-age=31536000; includeSubDomains";
await next();
});

When editors publish content, the CMS automatically purges affected URLs from the CDN. This is handled by the built-in cache invalidation system. No additional configuration is needed for this default behavior.

  1. Log into the management portal
  2. Navigate to your project
  3. Go to CDN > Purge Cache
  4. Choose purge scope:
    • Single URL — Enter the exact URL to purge
    • Path prefix — Enter a path like /en/blog/ to purge all matching URLs
    • Full purge — Clear the entire CDN cache
  5. Click Purge
Terminal window
opti cdn purge --url "https://www.example.com/en/blog/" --environment Production
opti cdn purge --all --environment Integration

Check the response headers to confirm caching behavior:

Terminal window
curl -I https://www.example.com/en/

Look for these headers:

HeaderMeaning
X-Cache: HITResponse served from CDN cache
X-Cache: MISSResponse fetched from origin
Age: 120Content has been cached for 120 seconds
Cache-Control: public, max-age=600Cacheable for 10 minutes
SymptomCauseFix
Pages never cacheCache-Control: private or no-storeCheck middleware and CMS output cache settings
Stale content after publishPurge not triggeringVerify CMS event handling; manual purge as fallback
Different content per userVary: Cookie creating too many variantsReduce cookie variation; use client-side personalization
Static assets not cachingMissing cache headers on static filesEnable static file caching middleware

URL patternCache-ControlRationale
/static/*, /assets/*public, max-age=31536000, immutableVersioned files; cache forever
/en/* (CMS pages)public, max-age=600Content pages; 10-minute cache
/api/*no-storeDynamic API responses
/episerver/*no-storeCMS editor interface
/util/*no-storeUtility and health endpoints