Systems status: [ OK ]
  • [ OK ]proxy
  • [ OK ]mailserver
  • [ OK ]sunrise
  • [ OK ]

Signed Exchanges in production

Signed Exchanges (SXG) are a powerful tool for improving website performance and security but there's some valuable lessons to be learned.

Signed Exchanges in production

Signed Exchanges (SXG) let a site cryptographically sign its content so that it can be served by third parties (like Google Search cache) while still being attributed to your origin. The promise is faster loads and better privacy — but getting SXG to work in production required more plumbing than I expected.

Certificates matter more than you think

To issue valid SXGs, you need a special SXG-compatible TLS certificate with the CanSignHttpExchanges extension. In practice, this means working with your CA (DigiCert is the common choice) and making sure the cert covers your canonical domain and any subdomains you plan to serve through SXG. Our first rollout failed silently because the cert only covered the www domain, not the bare domain. Browsers just rejected the SXG.

Caching is trickier than the marketing suggests

SXGs are signed snapshots. They expire quickly (often 7 days), which means your caching layer has to constantly refresh them. We ended up running a background job that re-generated SXGs daily, pushing them into our CDN. If you don’t plan this, users may end up with expired SXGs and fall back to slower paths.

Debugging is rough

There aren’t many tools for debugging SXG issues. Chrome DevTools shows whether SXG was used, but error messages are vague. For example, a “signature verification failed” could mean:

  • wrong cert
  • expired SXG
  • mismatch between signed URL and canonical URL

We built a small test harness that fetched our .sxg endpoints directly and verified headers with dump-signedexchange from Google’s tools repo.

Minimal setup snippet

Here’s the kind of fetch we used to test our signed bundles in staging:

const sxgUrl = "https://example.com/.well-known/sxg/index.sxg";
fetch(sxgUrl, { headers: { "Accept": "application/signed-exchange;v=b3" } })
  .then(res => console.log(res.headers.get("content-type")));

If things are wired correctly, you should see application/signed-exchange;v=b3 in the response.

The trade-offs

  • Pro: measurable LCP gains from prefetched SXGs in Google Search. Pages felt “instant” when navigated from SERPs.
  • Con: operational overhead. Cert management, re-signing cadence, CDN config, and lack of mature tooling all add complexity.

Takeaway: SXG works, but it’s not a flip-the-switch optimization. If you’re considering it for production, budget time for cert wrangling, caching strategy, and custom monitoring. It’s a sharp tool, but still a young one.