Third-Party CDNs

Layer0 is designed and built to be the component of your site to which your users will directly connect to from their devices. Such components are colloquially known as “edge components”. But sometimes you may prefer to run Layer0 behind a third-party CDN due to a pre-existing contract. Layer0 fully supports this use case but it’s important to call out some common pitfalls with this kind of network topology.

HTTP traffic protocol

In order for Layer0 to correctly determine the HTTP protocol (HTTP or HTTPS) used by the user agent, the third-party party CDN must use the same protocol that the user agent used. Thus, if the user agent has connected with HTTPS, the request passed to Layer0 must also be HTTPS, otherwise a security hole has been created, ripe for the man-in-the-middle attack. Conversely, if the user agent connected with HTTP, the request passed to Layer0 must also be HTTP so that the router rules that depend on the protocol continue to work correctly.


By default, Layer0 automatically redirects all HTTP traffic to HTTPS by issuing a 301 Moved Permanently redirect response. That redirect relies on the value of the host request header in order to form the value of the location response header (e.g., a host header value of docs.layer0.co will result in a location value of https://docs.layer0.co). When a third-party CDN is in front of Layer0, the host header may not be the public-facing domain but rather a domain to which the third-party CDN is routing traffic. In that case, the location header will have an incorrect value leading to an “escape” of the site from the public-facing domain to the private domain hosted on Layer0.

The same issue may affect all the custom redirects issued from Layer0 using the redirect router function or when leveraging the environment redirects feature.

There are two major techniques to solve these problems:

  1. Configuring the third-party CDN to rewrite the location header whenever it sees such a response from Layer0.
  2. Configuring Layer0 to serve the traffic on the same public facing domain and configuring the third-party CDN to send the traffic to Layer0 edge IPs with the public facing domain in the host header.

Split Testing

Layer0 offers fully featured split testing. When Layer0 is running behind another CDN, the CDN must be configured in a very specific way in order for split testing to work:

  1. Third-party CDN must be configured to not cache anything.
  2. The CDN must be configured to not affect any cookies that begin with layer0_.

Unless these conditions are met, the users will almost certainly receive a mix of content from both experiences in the split test, which can lead to a broken app and invalid split testing results.


When Layer0 is behind a third-party CDN, we strongly recommend that all caching on it be turned off. If, for whatever reason, you cannot do this, it is then your responsibility to first purge the cache on Layer0, and only afterwards on CDN - in that exact order. Failing to do so will almost certainly lead to a situation where stale responses that you wanted to purge are served from Layer0 to your CDN and cached there as non-stale responses before Layer0 itself is purged (so-called cache poisoning).

Caching and traffic metrics are another area that is affected by CDN caching or any kind of traffic shaping where Layer0 no longer sees all the traffic that your site is serving. If the third-party CDN is caching responses, then the perceived cache hit ratio on Layer0 will be lower than it actually is (Layer0 would only serve cache misses but never cache hits). If the third-party CDN is routing some traffic away from Layer0, then the traffic metrics will be affected as the Layer0 Developer Console will only provide statistics for the traffic that goes through Layer0.

Client IPs

When behind a third-party CDN, there is no way for Layer0 to securely determine the IP of the user agent that originated the request, hence the x-0-client-ip header will contain the IP of the third-party CDN rather than the actual user agent. Relying on headers like x-forwarded-for to determine the IP necessarily introduces a security hole where attackers can simply spoof the IP and work around IP allow/block and geolocation blocking features of the plaform. Since Layer0 uses the client IP to determine the geolocation headers, this means that geolocation headers will also have incorrect values.

In this situation, it is your responsibility to correctly set the client IP header and the dependent geolocation headers and pass it that way to Layer0 and upstream servers.

For example, if you wish to set the x-0-client-ip and related geolocation header, to the header values injected by the third-party CDN, you can add a shim for this which go at the top of your router:

.match('/:splat*', ({ setRequestHeader, removeRequestHeader }) => {
    setRequestHeader('x-0-client-ip', '${req:x-your-cdn-client-ip-header}')
    setRequestHeader('x-0-geo-country-code', '${req:x-your-cdn-geo-country-code-header}')
    setRequestHeader('x-0-geo-state-code', '${req:x-your-cdn-geo-state-code-header}')
    setRequestHeader('x-0-geo-city', '${req:x-your-cdn-geo-city-header}')
    setRequestHeader('x-0-geo-postal-code', '${req:x-your-cdn-geo-postal-code-header}')
    setRequestHeader('x-0-geo-latitude', '${req:x-your-cdn-geo-latitude-header}')
    setRequestHeader('x-0-geo-longitude', '${req:x-your-cdn-geo-longitude-header}')
    setRequestHeader('x-0-geo-asn', '${req:x-your-cdn-geo-asn-header}')


As mentioned above, when not running on edge, it is impossible for Layer0 to securely determine the client IP and other parameters on which the Layer0 security features rely. We strongly recommend that in that case, all security be performed on the third-party CDN.

Access Logs

Layer0 access logs continue to function normally but since they are not on the edge they may not include all of the traffic that comes to your site.

Allowing IPs

Layer0 does not block any validly formed HTTP traffic coming from any IP so there is no need to specifically allow the backend IPs of your third-party CDN.