Ludovic Frank - Freelance developer

Signed exchanges, when Google becomes your CDN (well, almost...)

ionicons-v5-k Ludovic Frank May 14, 2024
71 reads Level: Confirmed

Hi little wolves 🙂 (yep, it's the heat, it makes me cringe... deso),

Thank you for clicking on my article 😁, as usual we'll try to do quality and I hope you'll like it....

This week, we're going to talk about signed exchanges, it's a techno that's still little known and yet I find it super interesting, so we're going to share it all with you!

Briefly, what are signed exchanges?

Signed exchanges are a technology proposed by Google that allows you to cache your pages and assets (such as CSS) with Google (and other compatible companies), enabling them to preload your content to customers without making them connect to your servers.
That's it, the article's over, good day to you all 🤣! ... But no, let's go further.

A little background

It's January 2023, and I want to work on my CMS for a change, improve it and refresh it a bit...

While wandering around on the Internet, I came across an article (I can't remember where, and in English), which says that from now on, signed exchanges will also work with the "desktop" version of Google...

"Exchanges what? What's that all about?"

So I'm starting to get interested in the technology although I didn't expect much, in fact at one time SEO started to get on my nerves when Google came out with "AMP" pages (for "Accelerated Mobile Page").
Basically, with AMP, everything stayed with Google. Which was a problem for me, the browser has to display the actual URL of the content and not something starting with Google's domain...

So I started digging around, looking at the few resources on the subject (article, video), and as I dug deeper I realized that it was still very interesting and that I'd like to implement it on my site as well as that of Frères Marchand.

In concrete terms, how does it work?

Basically, you create a "binary packet", containing an HTTP request and its response, for example the HTTP request allowing you to load the page you're currently on, and the response containing the headers and body (in our case the HTML) of the page.

Once this packet has been created, we sign it with the private key linked to a certificate (the public key) containing the domain name and the "CanSignHttpExchanges" attribute. This signature allows clients to verify that the packet has been issued by the actual publisher of the resource and has not been altered. This will enable the browser to display your domain and URL in the address bar, even if, technically, the resource has been loaded from other servers.

How do I set up signed exchanges?

In fact, to set up signed exchanges, you need to set up a "reverse proxy" in front of your web server, which will intercept requests to create a signed exchange for a resource and create this signed exchange.When I did my research, only DigiCert and Google offered verification of this type of certificate.

On the practical side, I recommend this extension, compatible with all Chromium-based browsers, to check that a page works correctly with signed exchanges.

Compatible open source reverse proxies

First of all, forgive me if there's some confusion and not everything is clear in this chapter. Indeed, as the technology is young, it's a bit complicated to get the right information in the right place...

The module for NGINX

You can find a module for NGINXhere. As I haven't used it, I don't know what it's worth, but Google mentions it in its documentation.

The "sxg-rs" HTTP server

Here you'll find a Rust implementation of a reverse proxy that handles signed exchanges. That said, be careful, I don't really get the feeling that Google is promoting this project...

The web packager server

Here we go, another Go implementation. I'm more confident about this project.


Cloudflare offers activation of signed exchanges via a simple button in their interface, as part of their paid packages.

To activate it, go to "Spped" > "Optimization" > "Others".

Why did I choose Cloudflare as my reverse proxy?

They're one of the companies I "trust", and I've known them for 10 years (thanks, Korben, back in the day. By the way, his blog also uses signed exchanges) and they've never raised their prices, nor done anything really harmful (to my knowledge) despite the power they now have, besides, it's very easy to "get out" of their services, a simple DNS change and it's all over.

As for me, I wanted to overexploit signed exchanges. Caching HTML is fine, but the problem when you load a web page is the CSS above the floating line, which blocks the rendering of the page... so it has to be cached...

So I had the choice of either spending time implementing the reverse proxies proposed by Google in my infra, or letting Cloudflare do the work and focusing on the user experience, by looking at how I was going to cache the HTML and CSS.

I've chosen to trust Cloudflare, and if things don't work out, I can always go back.

How can I make the most of signed exchanges?

It all comes down to what your server sends back, in particular the "Cache" header, which will enable Google (or any other third party wishing to exploit your site's signed exchanges) to know how to handle it.

First you need to change the "private" to "public", to explain to the CDN and Google that they can keep this resource cached.

Next, you need to define the number of seconds the shared caches should keep the resource cached, which is done via the "s-maxage" variable.

In a Symfony project, here's how you do it:

Once you've made your function that adds the right headers to the response, all you have to do is create a "Listener", which will check whether it should modify the response, and if it should, then it calls our previously created function.

Here we see the "ROUTE_TO_CDN_CACHE" variable, which represents the Symfony routes you wish to make "public".

Imagine your users coming from Google and seeing a generic page, without their pretty username in the top right-hand corner, and for a store without their shopping cart... it's not great.

Google suggests using the "Vary: Cookie" header to tell the browser not to use the signed exchange and load the page from the server normally when the browser has a cookie registered for that domain.

Yeah, but I don't like it, it's not a good user experience... it's lame, we still want to enjoy ultra-fast loading times...

For the Frères Marchand online cheese shop, I also wanted signed exchanges, so how did I go about it?
Very simply, all the product pages, the home page, the categories, are set to "public" with the code I gave you earlier (I extracted this code from there, by the way), we use Varnish to clean up all the cookies sent by the client to the server to avoid any data leakage.

Once the page is loaded, we make a second HTTP request with Fetch, which checks whether we're connected, and if so, we replace the parts of the page that change... in our case, the user space and the shopping cart.

Finally, we create a local cache with the "localStorage", to keep the responses to this request, for page changes...

Voilàààààà, now we're exploiting signed exchanges properly... and everyone gets a good user experience 😍

Using signed exchanges with CSS files

Caching HTML with Google is all well and good... but we want instant loading , and we don't want the user to have to wait while the CSS is downloaded and interpreted to see the page.

To achieve this with Cloudflare's reverse proxy, simply add an HTTP header to your responses, using the "link" header, to tell the browser to preload a resource.


Cloudflare will take care of modifying the signed exchange generated for your HTML by adding a link to another signed exchange, the CSS one.

I'm using Cloudflare here, but the protocol clearly states that it's possible to create linked signed exchanges, so I assume that other implementations are compatible (but that you'll have to do otherwise).

Check that the signed exchange works correctly

All you need is your Chromium and Google-based browser...

Once you've set up your signed exchanges, you'll be able to see in your browser's "network" tab that directly from Google, it's loading your resources, even before the user clicks on your site. As a reminder, this won't create a connection to your servers (for confidentiality reasons).


I hope you've enjoyed this article and learned something from it.
Have a great week and see you soon 😁.