ZuploZuplo
LoginStart for Free
  • Documentation
  • API Reference
Introduction
Getting Started
    Develop in the portal
      1 - Setup Your Gateway2 - Rate Limiting3 - API Key Auth4 - Deploy5 - Dynamic Rate LimitingDynamic MCP Server - Quickstart
    Develop locally with the CLI
      1 - Setup Your Gateway2 - Rate Limiting3 - API Key Auth4 - Deploy5 - Dynamic Rate LimitingDynamic MCP Server - Quickstart
Concepts
Development
Policies
Handlers
API Keys
Rate Limiting
Caching
MCP Server
MCP Gateway
AI Gateway
Developer Portal
Monetization
GraphQL
Deploying & Source Control
Analytics
Observability
Networking & Infrastructure
    Overview
    Managed Dedicated
      OverviewSource ControlArchitectureNetworkingAWS Private NetworkingAzure Private NetworkingGCP Private NetworkingCustom DomainsFederated GatewaysArchitectureAkamai CDNCDN CachingAI-Powered Applications
    Managed EdgeSelf Hosted
    Custom Domains
    Securing Your Backend
    Web Application Firewalls
    DDoS Protection
Account Management
Programming API
Build with AI
Zuplo CLI
Migration Guides
Platform LimitsVersion Support PolicySecuritySupportTrust & ComplianceChangelog
powered by Zudoku
Managed Dedicated

Controlling Akamai CDN Caching

An Akamai property in front of a Zuplo gateway can absorb most of the read traffic an API serves. A catalog endpoint that returns the same payload to every caller doesn't need to reach the gateway 40,000 times an hour. It needs to reach it once every 30 minutes, and again the moment the catalog changes.

The CDN Cache Control policy writes the headers Akamai reads to make that happen: Edge-Control for the edge TTL, and Edge-Cache-Tag for the purge tags that let a content update invalidate the edge in seconds instead of waiting out the TTL.

How Akamai caching works

Client
Akamai CDN
Zuplo
Request (cache miss)
Forward to origin
Response + Edge-Control + tag
Response + Cache-Control (client TTL)
Press enter or space to select a node. You can then use the arrow keys to move the node around. Press delete to remove it and escape to cancel.
Press enter or space to select an edge. You can then press delete to remove it or escape to cancel.

What the edge does depends on the property configuration and on the headers Zuplo sends:

  1. Akamai Property Manager settings. The default caching rules configured in your CDN property.
  2. Origin response headers. What Zuplo sends, which can override or influence those defaults once the property is configured to honor them.

The edge TTL and the purge tags travel in headers the client never acts on, so the response the client receives carries only Cache-Control. Akamai also strips Edge-Cache-Tag before responses leave the edge unless the Cache Tag Visibility behavior is enabled, so tags stay internal by default.

For complete details on Akamai's caching behavior, see the Akamai caching documentation.

Set the edge TTL and purge tags

Add the CDN Cache Control policy to the outbound pipeline of any route whose responses are safe for a shared cache to replay. Set cdn to akamai and the policy renders everything else into Akamai's dialect.

Code
{ "name": "catalog-edge-cache", "policyType": "cdn-cache-control-outbound", "handler": { "export": "CdnCacheControlOutboundPolicy", "module": "$import(@zuplo/runtime)", "options": { "cdn": "akamai", "edge": { "maxAge": 1800 }, "client": { "visibility": "public", "maxAge": 60 }, "tags": ["catalog", "cities"] } } }

Akamai receives:

Code
Cache-Control: public, max-age=60 Edge-Control: cache-maxage=30m Edge-Cache-Tag: catalog,cities

The edge holds the response for 30 minutes and absorbs the traffic. Clients re-check every 60 seconds, so a purge of the cities tag reaches every caller within a minute rather than within half an hour.

The policy also removes an Edge-Control header your backend set that the policy is not writing itself, because a targeted header outranks Cache-Control and an upstream value would silently beat the TTL configured here.

respectUpstream is on by default. An upstream Cache-Control of no-store, no-cache, or private, or a Set-Cookie on the response, suppresses every edge header and purge tag. The backend keeps the final say even when the policy is applied broadly.

Splitting the edge TTL from the client TTL is the point of the policy. Because only Akamai reads Edge-Control, Cache-Control stays free to say whatever the client should do, down to private, max-age=0 for a response that requires an Authorization header but is identical for every caller:

Code
Cache-Control: private, max-age=0 Edge-Control: cache-maxage=5m

Akamai reads Edge-Control and ignores Cache-Control for its own decision, so it never sees the private. The edge caches; nothing downstream does. For the reasoning behind the split and the variations on it, see Cache at the CDN.

Don't put the Caching policy on the same route

Keep the Caching policy off any route that uses CDN Cache Control. The Caching policy serves a hit from an inbound policy, which short-circuits the pipeline before outbound policies run, so CDN Cache Control never executes on a gateway cache hit. Akamai then receives the copy that the Caching policy stored, and the Caching policy sanitizes every copy it stores: it drops several CDN cache headers (exactly which ones depends on the CDN) and overwrites Cache-Control with its own s-maxage (its TTL, 60 seconds by default). The edge and client TTLs collapse into one number. Cache misses run the full outbound stack and look correct, so the problem stays invisible until traffic warms the cache, and nothing logs it. Pick one place to cache.

Akamai-specific constraints

Stale serving needs Property Manager

edge.staleWhileRevalidate and edge.staleIfError have no Edge-Control equivalent. Rather than dropping those directives silently, the policy rejects the combination on Akamai. Two ways forward:

  • Configure stale serving in Property Manager. Leave edge.staleWhileRevalidate and edge.staleIfError unset, keep strategy at its default, and let the property decide how long the edge may serve a stale object while revalidating or while the origin is failing.
  • Set strategy to s-maxage. The edge TTL and the stale windows then travel in Cache-Control, which works on a property that honors origin Cache-Control but has not enabled Edge-Control.
Code
{ "name": "catalog-edge-cache", "policyType": "cdn-cache-control-outbound", "handler": { "export": "CdnCacheControlOutboundPolicy", "module": "$import(@zuplo/runtime)", "options": { "cdn": "akamai", "strategy": "s-maxage", "edge": { "maxAge": 1800, "staleIfError": 86400 }, "client": { "visibility": "public", "maxAge": 60 } } } }

s-maxage gives up the split: every directive becomes visible to clients, and caching at the edge without caching in the browser is no longer expressible. Prefer Property Manager for stale serving when the property already honors Edge-Control.

Vary suppresses caching

The vary option is off by default because of a behavior specific to Akamai: the edge skips caching any response carrying a Vary header until Cache ID Modification is configured in Property Manager. Turning vary on can therefore disable edge caching entirely while every response still looks correct. The policy logs a warning when vary is set together with cdn: akamai.

If a response genuinely varies by a request header, put that header in the cache key with Cache ID Modification instead of relying on Vary. Cache-key configuration is not expressible in response headers and stays CDN configuration.

Purge tag limits

Tags are validated against Akamai's limits before they are emitted, because the failure mode at the edge is silent truncation rather than an error.

LimitAkamai value
Maximum tag length128 characters
Maximum tags per response128
Maximum header size8192 bytes
Disallowed charactersspaces, commas, colons, brackets

A static tag in config/policies.json that violates a limit is a configuration error you fix before deploying. A tag produced at request time is dropped and logged as a warning instead.

Purge by tag with Fast Purge

Tagging responses is what makes targeted invalidation possible. A city sync that changes one record can invalidate city-42 across every edge server, leaving the rest of the catalog cached. Without tags, the choices are waiting out the TTL or purging far more than changed.

The policy emits the tags. It does not purge. Invalidation is a Fast Purge API call from your own tooling: a webhook on a content change, a step at the end of a sync job, or an operator-run script. Point it at the invalidate-by-tag endpoint with the same tag strings the policy emits.

Two Akamai details worth knowing:

  • Akamai strips Edge-Cache-Tag from responses before they reach end users unless the Cache Tag Visibility behavior is enabled. Enable it temporarily to confirm tags are landing, then turn it back off.
  • Tag names must respect the charset and limits above. See Akamai's guide to assigning cache tags.

Per-response cache rules

Static options cover a route. Per-entity tags such as city-42, a TTL that depends on a response header, or refusing to cache an empty result set cannot be expressed statically. For those, the policy takes a cacheConfig function that returns cache intent per response, and falls back to the static options whenever the function returns nothing.

The function returns intent rather than headers, so the same module works unchanged if the CDN in front of the gateway changes. See Per-response cache rules for the contract, the return values, and worked examples.

Configure Property Manager

None of the headers above matter until the property is configured to act on them. This is the part you cannot do from Zuplo.

  1. Caching behavior. Set the Caching Option to "Honor origin Cache-Control and Expires" and enable the directives you want honored (max-age, s-maxage, no-store, private, must-revalidate). Without this the property applies its own fixed TTL and ignores what the gateway sends.
  2. Honor Edge-Control. Confirm with your Akamai team that the property acts on Edge-Control. Edge-Control: cache-maxage outranks Cache-Control at the edge, which is what keeps the edge TTL out of the client's copy. If the property ignores it, set strategy to s-maxage until it is enabled.
  3. Default Max-age. Set a fallback TTL for responses that arrive with no cache headers, such as routes that do not carry the policy.
  4. Cache ID Modification. Configure this if a response varies by a request header. It is also the prerequisite for caching any response that carries a Vary header.
  5. Cache Tag Visibility. Off by default, which keeps Edge-Cache-Tag internal. Turn it on only while verifying that tags reach the edge.

For detailed CDN setup instructions, see Setting up Akamai CDNs.

Downstream cacheability

By default, Akamai sends clients the smaller of the origin's Cache-Control max-age and the remaining edge cache lifetime, so browsers never cache content longer than it remains valid at the edge. With the policy in place, the origin max-age is whatever client.maxAge sets; the edge TTL lives in Edge-Control and never reaches the client at all.

Property Manager's downstream cacheability settings can override this. For more information, see Akamai's downstream cacheability documentation.

Best practices

  1. Make the client TTL much shorter than the edge TTL. The edge is what you can purge; clients are not. A short client.maxAge with a long edge.maxAge gives you offload and control at the same time.
  2. Tag by entity, not just by route. city-42 lets you purge one city; cities alone forces you to purge them all.
  3. Leave respectUpstream on so the application keeps the ability to mark a response uncacheable.
  4. Verify at the edge, not just at the gateway. curl -I against the Zuplo URL shows the headers the policy emits. Whether Akamai honors them depends on the property configuration above.

Related resources

  • Cache at the CDN — the CDN Cache Control policy across every supported CDN
  • Caching in Zuplo — where to cache, and how to choose
  • CDN Cache Control policy — every configuration option in detail
  • Caching policy — the gateway-side alternative, not to be combined with CDN Cache Control
  • Akamai caching documentation — the complete Akamai caching reference
  • Akamai Fast Purge — purge by tag from your own tooling
Edit this page
Last modified on August 4, 2026
Akamai CDNAI-Powered Applications
On this page
  • How Akamai caching works
  • Set the edge TTL and purge tags
  • Akamai-specific constraints
    • Stale serving needs Property Manager
    • Vary suppresses caching
    • Purge tag limits
  • Purge by tag with Fast Purge
  • Per-response cache rules
  • Configure Property Manager
  • Downstream cacheability
  • Best practices
  • Related resources
JSON
JSON