PQC Edge and Identity, Advanced · 1 of 2
TLS Policy on a Managed Edge: Versions, Suites, Groups and the Strict-or-Compatible Decision
When a cloud edge ends TLS for you, which settings are really yours, and when should a path refuse a classical-only client instead of quietly falling back?
Put a website or an application programming interface (API) behind a managed cloud edge and something convenient happens: the edge answers every visitor's encrypted connection for you. It holds the certificate, picks the protocol, agrees the keys and passes the request on. That convenience has a price that only becomes visible when a new kind of cryptography arrives. Post-quantum key exchange, the protection against recorded traffic being decrypted by a future quantum computer, is negotiated in exactly the part of the handshake the edge now owns. So two questions land on your desk at once: which of the edge's settings actually decide what a client gets, and, for each path through it, should a connection that cannot use post-quantum key exchange be refused or allowed to fall back? This article answers both, using the public documentation of four Microsoft Azure edges as worked examples, and ends with a rule you can apply path by path and the evidence that proves the rule is working.
An edge is two connections and one policy you only partly own
A managed edge is a service run by a cloud provider that sits between the internet and your application and terminates Transport Layer Security (TLS), the protocol behind the padlock in a browser. Terminates means the encrypted connection from the visitor ends at the edge: the edge decrypts the request, inspects or routes it, and then opens a second, separate connection to your server, which the edge's documentation usually calls the origin or the backend. There are therefore two handshakes for every request, and they are negotiated independently. The first is between the visitor's software and the edge. The second is between the edge, now acting as a client, and your origin.
Every TLS 1.3 handshake settles three separate things, and it helps to keep them apart. The protocol version is the edition of TLS itself. The cipher suite decides how the bulk of the traffic is encrypted and checked once the connection is up. The key-exchange group, often still called the curve, decides how the two sides agree a fresh secret at the start, and it is the group that becomes post-quantum: a hybrid group such as X25519MLKEM768 mixes a classical elliptic-curve exchange with ML-KEM, the Module-Lattice-Based Key-Encapsulation Mechanism that the United States National Institute of Standards and Technology (NIST) standardised in 2024. The three choices are independent; a modern version and a strong suite can still sit on top of a purely classical group.
On a server you run yourself, you set all three. On a managed edge, the provider sets some of them, lets you set others, and decides the rest without telling you. That split is the whole subject of this article. It matters because a hybrid group protects the confidentiality of a connection against someone who records the traffic today and decrypts it once a large quantum computer exists, and on a managed edge the place where that protection is agreed is a place you may not be able to configure at all.
Four edges, four different sets of knobs
It is tempting to assume that every edge exposes the same controls. The public documentation, read on 29 October 2026, says otherwise. Azure Application Gateway, a regional web traffic load balancer, offers a TLS policy (its resource setting is still named SSL policy, after the older Secure Sockets Layer) that controls the minimum protocol version, the cipher suites and their order, either from a dated predefined policy such as AppGwSslPolicy20220101 or from a custom one. TLS 1.3 needs one of the 2022 predefined policies or the CustomV2 policy on the version 2 tiers, and the newer and older policy generations cannot coexist on one gateway, even though individual listeners can carry their own SSL profiles within that generation.
Azure Front Door, a global edge and content delivery network, sets a TLS policy per custom domain: predefined TLSv1.2_2023, which is the default, or TLSv1.2_2022, or a custom list of suites in your chosen order; TLS 1.3 is always enabled. Azure API Management, the gateway many teams put in front of their APIs and model endpoints, has a Protocols + ciphers page for the client side and the backend side, but its Consumption, Basic v2, Standard v2 and Premium v2 tiers, and the managed gateways of its workspaces, do not allow changes to the default cipher configuration. Azure App Service, the managed web hosting platform, lets you set a Minimum Inbound TLS Version, default TLS 1.2 with TLS 1.3 available as a hard minimum, and, on Basic tiers and above, a Minimum TLS Cipher Suite that blocks everything weaker than the one you pick from a fixed, ordered list.
Now look at the row that matters for post-quantum key exchange. None of the four TLS-policy pages documents a setting for key-exchange groups. The single exception sits outside the conceptual pages: the Azure Resource Manager (ARM) schema for Front Door custom domains, API version 2026-07-01, added a server TLS group policy with the values Standard, Enhanced and Custom, and a custom group list that may contain X25519MLKEM768, SecP256r1MLKEM768 and SecP384r1MLKEM1024 alongside classical groups. The Azure command-line interface (CLI) exposes the same fields as --server-tls-group-policy and --server-tls-groups. The table puts the four side by side.
| Edge | What you can set | Key-exchange groups | Edge to origin |
|---|---|---|---|
| Application Gateway v2 | Minimum version, suites and order; predefined or custom; gateway-wide generation, per-listener profiles | Not documented | Prefers TLS 1.3, falls back to 1.2; version and suites not customizable |
| Front Door Standard and Premium | Minimum version, suites and order per custom domain; TLS 1.3 always on | Schema 2026-07-01: Standard, Enhanced or Custom list incl. three hybrids; contents of Standard and Enhanced not described | Best version the origin reliably accepts, TLS 1.2 or 1.3 |
| API Management | Client and backend protocols and ciphers, except on Consumption and v2 tiers and workspace gateways | Not documented | Backend protocols selectable, backend TLS 1.3 optional |
| App Service | Minimum inbound version; minimum cipher suite from a fixed list (Basic and above) | Not documented | Front end to worker encrypted with end-to-end TLS on Premium plans |
Set, fixed, or silent: the three states of every setting
A cleaner way to read any edge's documentation is to sort every negotiated setting into one of three states. In the first, you set it: the minimum version on all four services is like this. In the second, the provider fixes it and says so: App Service states that the two TLS 1.3 suites are fixed and cannot be customized, and Application Gateway states that the version and suites it uses towards your backend cannot be customized. In the third, the provider decides and does not say: the key-exchange groups offered by Application Gateway, API Management and App Service fall here, because their pages describe versions and suites and are silent on groups.
The third state is not a criticism; it is a planning fact. A silent setting is still a decision, made by the provider's TLS stack and changeable on the provider's schedule. App Service's documentation shows what silence can hide in a neighbouring dimension: by default its front end chooses the most secure suite that both sides support, but if a client supports only weak suites, it chooses a weak one, unless you set a minimum. Silent behaviour tends to be compatible behaviour, which keeps visitors connected and leaves your security floor wherever the weakest client puts it.
Front Door shows a fourth situation that sits between the second and third states: a setting that exists in the resource schema and the command-line interface, but whose behaviour the conceptual documentation does not yet describe. The schema tells you that a Custom group list can include three ML-KEM hybrids. It does not tell you what Standard or Enhanced contain, which of them applies when you set nothing, or what happens to a client when the custom list contains only hybrid groups. Treat a schema field as proof that a knob exists, never as proof of what it does. Prove the behaviour by probing a non-production custom domain you own before relying on it, and record the date you checked, because the conceptual pages will change.
Strict and compatible, defined precisely
Two postures are possible for any path, and it is worth defining them sharply because loose definitions produce loose policies. Strict means a handshake that does not land on a hybrid post-quantum group fails, on purpose. Strict is a form of fail closed: when the protection you require cannot be agreed, the connection does not happen. Compatible means a hybrid group is preferred and used when both sides support it, and a classical group is accepted when they do not, with the share of classical connections counted rather than ignored.
Neither posture is more secure in the abstract. Strict trades reachability for a guarantee: every connection that succeeds is protected against later decryption, and every client that cannot keep up is locked out. Compatible trades the guarantee for reach: nobody is locked out, and some connections remain exposed to record-now, decrypt-later collection. The useful question is never which posture is better, but which posture fits a particular path, given who its clients are and how long the data on it must stay confidential.
The two postures fail differently, and that difference shapes how you operate them. A strict path that turns away a client produces a failed handshake, which happens before any request exists. Nothing reaches the application, so nothing appears in the application's own logs, and the client sees a connection error rather than a helpful message. By contrast, API Management answers a client that uses a protocol version below the minimum with an HTTP 400 error explaining that the version is not permitted, because version enforcement there happens after the handshake. Plan the support story for strict paths accordingly: the evidence of a refused client lives on the client side or in synthetic tests, not in your request logs.
A decision rule for each path, not for the whole estate
Make the decision path by path, because one edge usually carries traffic from very different clients. The first question is whether you control every client on the path. If your own service, job or AI agent calls your own API through the edge, you can name every piece of client software, upgrade it and test it. If the path serves the public, partners or third-party integrations, you cannot. The second question, for paths you control, is whether every client stack on the path already offers a hybrid group; until it does, strict would break your own traffic.
That gives three outcomes. Where you control every client and every client offers a hybrid group, strict is viable and is the right choice for data whose confidentiality must outlive the arrival of a capable quantum computer. Where you control every client but some cannot yet offer a hybrid group, run compatible, measure, and switch to strict when the last client is upgraded. Where you do not control the clients, run compatible with a hybrid preference, publish an internal target for the hybrid share, and measure the fallback rate for each client population; strict there would simply lock out people you cannot reach.
Here is the practical twist for edges with no group setting. Strictness does not have to live on the edge. On a path you control, the client can offer only hybrid groups, and then it fails closed if the edge cannot agree one. Python 3.15 adds SSLContext.set_groups for exactly this, and OpenSSL's tools accept a -groups list. Mixed audiences can be split by hostname: Front Door's TLS settings, including the new group fields, belong to each custom domain, so a machine-to-machine hostname can be strict while the human-facing hostname stays compatible. Application Gateway can give each listener its own SSL profile, but because no group setting is documented there, a strict listener on that edge still depends on client-side strictness.
import socket, ssl
ctx = ssl.create_default_context()
ctx.minimum_version = ssl.TLSVersion.TLSv1_3
ctx.set_groups("X25519MLKEM768") # no classical group offered: fail closed
with socket.create_connection((host, 443)) as raw:
with ctx.wrap_socket(raw, server_hostname=host) as tls:
log(host, tls.version(), tls.group())Evidence: proving which group each population actually gets
A decision without evidence is a hope, and the evidence for this decision is harder to gather than it looks. The access logs the edges document record the protocol version and the cipher suite of each request. Application Gateway logs sslProtocol and sslCipher for the client side and BackendSslProtocol and BackendSslCipher for the origin side; Front Door logs SecurityProtocol and SecurityCipher. None of the documented fields names the key-exchange group. The edge can therefore tell you your TLS 1.3 share, which is the ceiling for hybrid use since only TLS 1.3 carries these groups, but not your hybrid share.
Measure the group where it is visible. On clients you own, log it: Python 3.15's SSLSocket.group method returns the group agreed on a connection, and other runtimes expose similar fields. For populations you do not own, run synthetic probes that imitate each population's client software. Where you terminate TLS yourself, for example on an origin server running nginx with OpenSSL 3, the $ssl_curve variable records the agreed group for each connection, which at least covers the second hop. Four numbers then describe a path: the hybrid share of TLS 1.3 handshakes per client population, the classical fallback rate, the handshake failure rate per population, and the extra round trips.
Extra round trips deserve a sentence of their own, because the provider's own documentation supplies the example. When a client's first guess at a group is not one the server accepts, TLS 1.3 requires the server to ask again with a HelloRetryRequest, which costs a round trip. Front Door's TLS pages note that TLS 1.3 clients should prefer one of the elliptic curves it lists to avoid exactly that latency. A hybrid group placed first by a client, against an edge that does not accept it, pays the same price. Watch latency per population when you change either end.
openssl s_client -connect strict.example.com:443 -tls1_3 -groups X25519MLKEM768 -brief < /dev/null
openssl s_client -connect strict.example.com:443 -tls1_3 -groups X25519 -brief < /dev/nullThe second connection and the mechanics of change
Everything so far concerns the visitor's handshake. The connection from the edge to your origin is a separate negotiation in which the edge is the client, and its controls are thinner still. Application Gateway prefers TLS 1.3 towards backends, falls back to TLS 1.2, and states that the backend version and suites cannot be customized. Front Door negotiates the best version the origin can reliably and consistently accept. API Management lets you choose backend protocols and makes backend TLS 1.3 optional, warning that it breaks backends that rely on certificate renegotiation. App Service's end-to-end option encrypts the hop from its front end to the worker running your code. None documents backend groups, so a hybrid handshake at the front says nothing about the hop behind it.
How a change is applied matters as much as what is changed. On API Management, protocol and cipher changes can take 15 to 45 minutes or longer, and the Developer tier is briefly unavailable while they apply. On Application Gateway the choice of policy generation affects the whole gateway. On Front Door the settings belong to one custom domain, which makes a canary hostname natural. On App Service the settings belong to one app, and Azure Policy can audit the minimum TLS version across many apps so drift is visible.
Put those facts into a rollout that can be undone in one step. Record the current settings before touching anything. Change a canary hostname or a single listener first, probe it with both a hybrid-only and a classical-only client, and compare failure rates and latency per population for long enough to see weekly traffic patterns. Only then widen the change. Keep the previous policy written down next to the probe results, so rolling back is a single, rehearsed change rather than an investigation conducted during an outage.
- Record the edge's current version, suite and, where it exists, group settings.
- Change one canary hostname or listener.
- Probe it with a hybrid-only and a classical-only client.
- Compare failure rate and latency per client population.
- Widen the change, keeping the old settings one step away.
What this means for AI agents and the people who run them
AI agents travel through exactly these edges. An agent that calls a large language model often reaches it through API Management acting as a model gateway; an agent that calls tools reaches them through Front Door or Application Gateway in front of the tool servers. Each of those calls carries prompts, retrieved documents and tool results, and some of that content, such as contracts, health records or credentials pasted into a conversation, must stay confidential for years. That is precisely the kind of traffic that rewards a recorder today and a quantum computer later.
Agents also make client control both easier and harder. Easier, because the agent-to-own-tool path is a path where you control both ends, so strict is achievable. Harder, because one agent host often runs several runtimes: a .NET host process, a Python tool runner and a Node.js helper on the same machine can each offer different groups, since each uses its own TLS library. The practical pattern is to set strictness in the agent's own HTTP client for the agent-to-own-tool path, keep the human chat front end compatible, and log the agreed group per agent call wherever the runtime exposes it.
For the people who own these platforms, the decisions are concrete. Decide, per hostname, which paths are strict and which are compatible, and write the reason next to the decision. Separate machine-to-machine hostnames from human-facing ones so the two postures do not fight. Ask each edge's owners which of the three states each setting is in, and do not accept a schema field as an answer until a probe confirms it. Above all, insist on numbers: a hybrid share per population that rises over time, a fallback rate you can explain, and a failure rate that stays flat.
Key takeaways
- A managed edge runs two independent handshakes, and the key-exchange group, where post-quantum protection lives, is the setting most often decided by the provider without documentation.
- Sort every setting into three states: you set it, the provider fixes and states it, or the provider decides silently; a schema field alone proves only that a knob exists.
- Strict fails closed and buys a guarantee with reachability; compatible keeps everyone connected and must measure its classical share.
- Choose strict per path where you control every client and every client offers a hybrid group; strictness can be enforced by the client when the edge has no group setting.
- Edge logs record version and suite, not the group, so measure the group at clients, probes or a terminator you own, per client population.
Glossary
- Managed edge
- A cloud provider's service that terminates visitors' TLS connections in front of your application and opens its own connection to your origin.
- Key-exchange group
- The method two sides use to agree a fresh secret at the start of a TLS connection, also called the curve; hybrid post-quantum groups live here.
- Hybrid group
- A key-exchange group, such as X25519MLKEM768, that combines a classical elliptic-curve exchange with ML-KEM so both would have to be broken.
- Strict posture
- A path policy under which a connection that cannot agree a hybrid group is refused rather than allowed to fall back.
- Compatible posture
- A path policy that prefers a hybrid group but accepts a classical one, while measuring how often that happens.
- HelloRetryRequest
- A TLS 1.3 message a server sends when the client's first key-exchange guess was not acceptable, costing an extra round trip.
- Origin
- Your own server or service that an edge forwards requests to over a second, separately negotiated connection.
- Resource schema
- The machine-readable definition of a cloud resource's settings, used by templates and the command-line interface, which can list a field before the prose documentation explains it.
Further reading
Sources
This article is based only on public, authoritative Microsoft documentation.
- TLS policy overview for Azure Application Gateway — Microsoft Learn
- Azure Application Gateway monitoring data reference — Microsoft Learn
- Configure an Azure Front Door TLS policy — Microsoft Learn
- End-to-end TLS with Azure Front Door — Microsoft Learn
- Microsoft.Cdn/profiles/customDomains 2026-07-01 (resource schema) — Microsoft Learn
- API change log for Microsoft.Cdn/profiles/customDomains — Microsoft Learn
- az afd custom-domain (Azure CLI) — Microsoft Learn
- Azure Front Door logs — Microsoft Learn
- Manage protocols and ciphers in Azure API Management — Microsoft Learn
- What is TLS/SSL in Azure App Service? — Microsoft Learn
- RFC 10024: Post-quantum hybrid ECDHE-MLKEM Key Agreement for TLSv1.3
- RFC 8446: The Transport Layer Security (TLS) Protocol Version 1.3
- openssl-s_client (OpenSSL 3.5 manual)
- ssl — TLS/SSL wrapper for socket objects (Python 3.15)