These settings govern delivery performance and how the edge interacts with your origin and with end users. The two caching templates are where most of the value is: effective caching reduces origin load, saves bandwidth, and puts assets closer to your users.
dnsAsyncRefresh
dnsAsyncRefresh {
"name": "dnsAsyncRefresh",
"options": {
"enabled": true,
"timeout": "5h"
}
}Defines how edge servers behave when your origin's DNS A record expires. Enabled, the edge forwards the current request using the expired record while refreshing the record in the background. Disabled, the edge has to resolve DNS before forwarding, and a slow or failed resolution turns into user-perceived latency or a denial of service.
timeout is how long an expired record stays usable while the refresh happens. 5 hours is the Ion best practice, and it's an intentional override: the behavior's own default is 2 hours.
timeoutis only available whileenabledistrue. If you setenabledtofalseand later back totruewithout restatingtimeout, you get the behavior default of 2 hours, not Ion's 5.
For finer control over origin timeouts, add the optional readTimeout and connectTimeout behaviors to a rule.
http3
http3{
"name": "http3",
"options": {
"enable": true
}
}HTTP/3 replaces TCP with the IETF QUIC protocol, which means faster connection setup and more
efficient stream handling.
Requires TLS 1.3 for client-to-edge requests.
http2
http2{
"name": "http2",
"options": {
"enabled": ""
}
}HTTP/2 gives you concurrent downloads over one TCP connection, object prioritization, and header compression. It's enabled on the platform and can't be turned off, which is why the option carries an empty placeholder value rather than a boolean. Send the object as the template delivers it.
allowTransferEncoding
allowTransferEncoding{
"name": "allowTransferEncoding",
"options": {
"enabled": true
}
}Allows chunked transfer encoding, which improves performance for large content by breaking data into chunks so one large download can't block a connection.
- Chunked transfer encoding has to be enabled on your origin too.
- Don't set this to
falseif you use HTTP/2 or HTTP/3. Denying chunked encoding there results in a denial of service for clients requesting chunked content — and HTTP/3 is on by default in this same template.
sureRoute
sureRoute{
"name": "sureRoute",
"options": {
"enabled": true,
"type": "PERFORMANCE",
"testObjectUrl": "/akamai/sureroute-test-object.html",
"toHostStatus": "INCOMING_HH",
"raceStatTtl": "30m",
"forceSslForward": false,
"enableCustomKey": false,
"srDownloadLinkTitle": ""
}
}SureRoute finds the fastest path between edge servers and your origin by racing candidate routes, and keeps failover paths available. It's aimed at non-cacheable content — for anything cacheable, serving from the edge beats any origin route, so the platform disables SureRoute automatically when it detects cacheable content.
| Option | Ships as | Why |
|---|---|---|
type | PERFORMANCE | Races three simultaneous paths, triggered by real end-user requests for non-cacheable content, and promotes the fastest. Adapts as internet conditions change. The alternative is CUSTOM_MAP, which needs a map from Akamai. |
testObjectUrl | /akamai/sureroute-test-object.html | The object the races request. The path is seeded for you, but you must put the object on your origin. |
toHostStatus | INCOMING_HH | Races use the forward host header you already set for your origin, so they test the same request path real traffic takes. Use OTHER with toHost to race a different hostname. |
raceStatTtl | 30m | How long a race result is reused before the next race. Long enough to amortize the cost of racing, short enough to track changing conditions. |
forceSslForward | false | Races follow the request's protocol. Set true if your origin only accepts HTTPS. |
enableCustomKey | false | Race results are stored per origin hostname. With true, customStatKey sets the grouping explicitly. |
Disable SureRoute if this configuration serves only cacheable content.
earlyData
earlyData{
"name": "earlyData",
"options": {
"enabled": true
}
}Early Data (0-RTT) is a TLS 1.3 feature that lets a client resuming a session send data during the handshake, removing a round trip and reducing time to first byte. Ion enables it because the latency win applies to exactly the requests Ion exists to accelerate.
Akamai only applies Early Data to GET requests without query parameters, which limits exposure to replay attacks.
Before you leave this on, confirm:
- Secure connection. Your certificate's deployment settings must have TLS 1.3 enabled.
- Compatibility. Early Data is incompatible with the
enforceMtlsSettingsbehavior. You can't
use both. - Origin support. Your origin must recognize the
Early-Data: 1header and should return HTTP 425 (Too Early) for requests it can't safely process over 0-RTT.
To extend 0-RTT beyond GET requests, add the earlyDataAdvanced behavior to a rule. It isn't part of the Ion default settings.
cachingTemplate
cachingTemplateThe largest setting in the template, and the one most worth understanding before you change anything. "Origin offload" is the share of content Akamai serves instead of your origin, and this is where you control it.
{
"name": "cachingTemplate",
"options": {
"cachingOption": "CACHE_FEW_OBJECTS",
"tieredDistribution": true,
"validateEntityTag": true,
"removeVaryHeader": false,
"cacheKeyQueryParams": "INCLUDE_ALL_ALPHABETIZE_ORDER",
"cacheHttpTemporaryRedirects": false,
"cacheHttpErrorResponse": true,
"cacheHttpErrorTtl": "10s",
"cacheHttpErrorPreserveStale": true,
"prefreshCache": true,
"prefreshCacheTtlPercentage": 90,
"applyCssJsCaching": true,
"cacheCssJsExtensions": ["css", "js"],
"cacheCssJsPolicy": "MAX_AGE",
"cacheCssJsTtl": "7d",
"cacheCssJsForceRevalidateCache": false,
"applyFontsCaching": true,
"cacheFontsExtensions": ["eot", "woff", "woff2", "otf", "ttf"],
"cacheFontsPolicy": "MAX_AGE",
"cacheFontsTtl": "30d",
"cacheFontsForceRevalidateCache": false,
"applyImagesCaching": true,
"cacheImagesExtensions": ["jpg", "jpeg", "png", "gif", "webp", "jp2", "ico", "svg", "svgz"],
"cacheImagesPolicy": "MAX_AGE",
"cacheImagesTtl": "30d",
"cacheImagesForceRevalidateCache": false,
"applyFilesCaching": true,
"cacheFilesExtensions": ["pdf", "doc", "docx", "odt"],
"cacheFilesPolicy": "MAX_AGE",
"cacheFilesTtl": "7d",
"cacheFilesForceRevalidateCache": false,
"applyHtmlCaching": true,
"cacheHtmlExtensions": ["html", "htm", "php", "jsp", "aspx", "EMPTY_STRING"],
"cacheHtmlPolicy": "NO_STORE",
"applyOthersCaching": true,
"cacheOthersExtensions": ["aif", "aiff", "au", "avi", "bin", "..."],
"cacheOthersPolicy": "MAX_AGE",
"cacheOthersTtl": "7d",
"cacheOthersForceRevalidateCache": false
}
}cacheOthersExtensions is abbreviated here.
Caching policy
cachingOption ships as CACHE_FEW_OBJECTS — cache specific objects, selected by file extension. This is an override of the behavior's CACHE_ALL default, and it's the decision that shapes the rest of the setting: it's why all six apply*Caching switches are on and why each content type gets its own policy, TTL, and extension list.
| Value | Effect |
|---|---|
CACHE_FEW_OBJECTS | Ships as this. Per-content-type caching by file extension. Makes the apply*Caching options available. |
CACHE_ALL | One policy for everything. Makes cacheTtl and cacheForceRevalidate available instead. |
CACHE_NONE | No edge caching. Hides tieredDistribution, cacheKeyQueryParams, prefreshing, and the per-type options. |
SwitchingcachingOptionchanges which options are validThe per-type options (
applyImagesCaching,cacheImagesTtl, and the rest) are only available underCACHE_FEW_OBJECTS.cacheTtlandcacheForceRevalidateare only available underCACHE_ALL.tieredDistribution,validateEntityTag,removeVaryHeader,cacheKeyQueryParams,cacheHttpErrorResponse, and the prefresh options needCACHE_ALLorCACHE_FEW_OBJECTS, so a switch toCACHE_NONEinvalidates all of them. Rebuild the options object when you change this value.
Content-specific caching
The TTLs follow how often each content type actually changes:
| Content type | Ships as | Why |
|---|---|---|
| CSS and JavaScript | MAX_AGE, 7d | Versioned or fingerprinted in most build pipelines, so a week of caching is safe. |
| Fonts | MAX_AGE, 30d | Effectively static once published. |
| Images | MAX_AGE, 30d | Static once published, and the biggest offload win by bytes. |
Files (pdf, doc, docx, odt) | MAX_AGE, 7d | Documents change more often than images and are more likely to be replaced in place. |
| HTML | NO_STORE | HTML changes frequently and is the most likely to carry per-user content, so edge servers always check the origin. |
| Other | MAX_AGE, 7d | A broad extension list of media, archives, and binaries, at a conservative TTL. |
Each type has three companion options: apply<Type>Caching turns the block on, cache<Type>Policy is MAX_AGE or NO_STORE, and cache<Type>Ttl sets the duration. A MAX_AGE policy also makes cache<Type>ForceRevalidate available.
Never cache files containing personally identifiable information (PII). The
Filesblock caches
doc,docx, andodtfor 7 days by default — if any of those are per-user documents on your origin, narrow the extension list or override the path in a rule.
EMPTY_STRINGin the HTML extension list
cacheHtmlExtensionsincludes the literal"EMPTY_STRING", which matches URLs with no file extension. That's what makes the HTMLNO_STOREpolicy apply to paths like/and/aboutrather than only to/index.html. Keep it unless you deliberately want extensionless URLs falling through to another block.
Cache key, validation, and offload
| Option | Ships as | Why |
|---|---|---|
cacheKeyQueryParams | INCLUDE_ALL_ALPHABETIZE_ORDER | All parameters stay in the cache key, but reordered alphabetically, so ?a=1&b=2 and ?b=2&a=1 are one object instead of two. A straight cache-hit improvement with no change to what users receive. The other values are INCLUDE_ALL_PRESERVE_ORDER, IGNORE_ALL, INCLUDE, and IGNORE; the last two take a parameter list. |
tieredDistribution | true | Adds a parent caching tier between edge servers and your origin. An edge miss checks the parent before going to your origin. Note that it creates midgress traffic (edge-to-parent), which appears as its own category in traffic reports. |
validateEntityTag | true | Compares a request's If-None-Match against the cached object's ETag and answers 304 Not Modified when they match, so a revalidation costs headers instead of a body. This is in addition to Last-Modified / If-Modified-Since validation. |
removeVaryHeader | false | Akamai doesn't cache responses carrying a Vary header, even when the content is otherwise cacheable. Removing the header raises hit rates but discards the origin's statement that the response varies — so it ships off, as a deliberate opt-in. |
prefreshCache | true | Refreshes an object asynchronously just before it expires, so the next user doesn't wait on your origin. |
prefreshCacheTtlPercentage | 90 | Refresh starts at 90% of the TTL — for a 10-minute TTL, at the 9-minute mark — leaving your origin time to respond before the object actually expires. Prefresh only triggers if a request arrives inside that window, so set it low enough to cover your origin's typical response time. |
cacheHttpTemporaryRedirects | false | 302 and 307 responses are temporary by definition, so they aren't cached. Set true to cache them the way 301 and 308 are cached. |
cacheHttpErrorResponse | true | Caches error responses (204, 305, 404, 405, 414, 501–504) so repeated requests for missing content don't reach your origin — protection that matters most during an outage. |
cacheHttpErrorTtl | 10s | Long enough to absorb a burst, short enough that a fixed error clears almost immediately. 0 sends every request to your origin. |
cacheHttpErrorPreserveStale | true | While your origin is struggling, serve a stale cached object rather than a fresh error. |
Error responses larger than 64 KB — often custom 404 pages — aren't cached by default. Contact your Akamai representative to raise the limit.
downstreamCacheTemplate
downstreamCacheTemplateWhere cachingTemplate governs the edge, this governs caching downstream of the edge: browsers, mobile apps, and corporate proxies.
{
"name": "downstreamCacheTemplate",
"options": {
"cacheOption": "ALLOW",
"cacheLifetime": "LESSER",
"sendHeaders": "CACHE_CONTROL",
"sendPrivate": false,
"bustUncacheable": true,
"applyHtmlCaching": false
}
}| Option | Ships as | Why |
|---|---|---|
cacheOption | ALLOW | Standard downstream storage is permitted. Alternatives: MUST_REVALIDATE (store but revalidate before every use), BUST (never store), TUNNEL_ORIGIN (pass your origin's headers through unchanged), NONE (send no cacheability headers and let browser defaults apply). |
cacheLifetime | LESSER | Clients are told to cache for whichever is shorter: the time left in the edge cache or the value from your origin headers. The conservative choice — a client never holds content longer than the edge would. |
sendHeaders | CACHE_CONTROL | Cache-Control alone is unambiguous and is what every current client honors. Expires is a legacy duplicate that can conflict. Other values: CACHE_CONTROL_AND_EXPIRES, EXPIRES, PASS_ORIGIN. |
sendPrivate | false | Adding private restricts caching to the end user's own device, which also prevents shared-proxy caching. Off by default; turn it on for per-user responses. |
bustUncacheable | true | For content the edge won't cache, actively prevent downstream caching by sending Expires: [current time], Cache-Control: max-age=0, Cache-Control: no-store, Cache-Control: no-cache, and Pragma: no-cache. This is what keeps uncacheable responses — the Ion template's NO_STORE HTML among them — out of browser and proxy caches. |
applyHtmlCaching | false | No separate downstream policy for HTML, so HTML follows the settings above. |
cacheLifetime is only available with cacheOption: ALLOW, and ttl only with cacheLifetime: FROM_VALUE. Setting ttl to 0 forces revalidation and sends all cache-busting headers downstream, whatever sendHeaders says.
Turning on applyHtmlCaching opens a parallel set of options for HTML alone — cacheHtmlOption, cacheHtmlExtensions, cacheHtmlLifetime, cacheHtmlTtl, cacheHtmlSendHeaders, cacheHtmlSendPrivate, cacheHtmlBustUncacheable.
