Routing API Traffic to Your CDN: Cache Headers
Scaling an API means managing server load. One of the most effective ways to reduce that load is caching responses at the CDN edge. Cloudflare and other CDNs sit between your users and your origin server. They can serve responses directly, without touching your backend. But this only works if your HTTP headers are configured correctly.
The Misconception Around ETag and Keep-Alive
Two headers cause a lot of confusion here: ETag and Keep-Alive. Developers often assume these will cache an API response. They do not.
Keep-Alive maintains an open TCP connection. It prevents the server from repeating the TLS handshake on every request. That reduces connection latency. It does not store your JSON anywhere.
ETag is a fingerprint of your response payload. When a cached response expires, the CDN sends a conditional request to your server asking if the content has changed. If it has not, your server responds with 304 Not Modified. No response body is sent, which saves bandwidth.
But your server still runs. It still executes application logic. It still queries the database to confirm whether the ETag is valid. The compute load on your backend does not go away.
The Cache-Control Solution
To prevent requests from reaching your server at all, you need the Cache-Control header. This tells the CDN to store the response and serve it directly to users for a defined period.
Add this header to your API response:
Cache-Control: public, max-age=3600, s-maxage=3600
Here is what each directive does:
public— Allows any proxy or CDN to cache the response.max-age=3600— Tells the user's browser to cache the response for 3600 seconds.s-maxage=3600— Targets shared caches like Cloudflare specifically. Edge nodes will hold the response for 3600 seconds.
s-maxage takes precedence over max-age for CDNs that support it. Cloudflare does.
Configuring Cloudflare to Respect Your Headers
Sending the right header is not enough on its own. CDNs are conservative by default. Cloudflare automatically caches static assets like images and stylesheets. It does not cache JSON or API routes. Even with correct headers, Cloudflare will bypass the cache for your API endpoint unless you explicitly tell it not to.
You need a Cache Rule.
- Open the Caching section in your Cloudflare dashboard.
- Create a new Cache Rule.
- Set the target to your specific API path.
- Set cache eligibility to Eligible for cache.
- Set Edge TTL to Respect origin header.
With this in place, Cloudflare reads your s-maxage directive and caches the response at the edge. Subsequent requests for that resource never reach your origin.
Configuring CloudFront to Respect Your Headers
CloudFront handles this differently from Cloudflare. Instead of Cache Rules, CloudFront uses Cache Policies and Origin Request Policies attached to a distribution behavior.
By default, CloudFront uses its own TTL settings and may ignore your Cache-Control headers entirely. You need to explicitly configure it to use your origin headers.
Create a Cache Policy that respects origin headers:
- Open the CloudFront console and select your distribution.
- Go to the Behaviors tab and edit the behavior for your API path.
- Under Cache key and origin requests, select Cache policy.
- Create a new policy. Set the TTL settings to use the origin's
Cache-Controlheader by setting the minimum TTL to 0 and leaving the default and maximum TTL high enough to not override yours-maxage. - Attach the policy to your behavior.
Alternatively, you can use the AWS-managed policy CachingOptimized as a starting point, but it is built for static assets. For API responses, a custom policy gives you more control.
One important difference from Cloudflare: CloudFront respects Cache-Control: s-maxage but also checks whether your origin is returning Cache-Control: no-cache or private. Either of those will prevent caching regardless of your policy configuration. Make sure your API is not setting conflicting headers elsewhere in your middleware stack.
Once configured, CloudFront edge nodes will serve cached responses directly from the nearest point of presence. Your origin receives a request only when the cache is cold or the TTL has expired.
When to Use Each Header
These three headers are not competing options. They serve different purposes and work well together.
| Header | What it does | Does it offload the backend? |
|---|---|---|
Keep-Alive |
Reuses TCP connections | No |
ETag |
Avoids resending unchanged responses | Partially |
Cache-Control |
Stores and serves responses at the edge | Yes |
Use Keep-Alive to reduce connection overhead. Use ETag to minimize bandwidth when cached content expires. Use Cache-Control combined with a CDN Cache Rule to fully offload traffic from your backend.
Summary
If your API serves data that does not change on every request, caching at the CDN edge is worth doing. The setup is straightforward. Set Cache-Control: public, s-maxage=3600 on your response and configure a Cache Rule in Cloudflare to respect it. Your origin server will stop seeing repetitive, redundant requests. That is the goal.
Solving an engineering problem? Let us know. Email us your problem and we will get back.