Azure OpenAI to Microsoft Foundry: Fixing Private Endpoint & DNS Failures Before the Auto-Upgrade
Microsoft is automatically flipping eligible Azure OpenAI resources to Foundry — the same resource, mutated from kind: OpenAI to kind: AIServices. A Foundry resource answers on three FQDNs where Azure OpenAI answered on one. If the two new private DNS zones do not exist, every new Foundry capability resolves to a public IP or fails outright. This is how to get ahead of it.
# 1. Auto-upgrade status on a private-networked resource (JSON view, API 2026-01-15-preview):
"foundryAutoUpgrade": {
"mode": "Enabled",
"scheduledAt": null,
"status": "Failed: PrivateNetworking"
}
# 2. After a MANUAL kind-flip, the new Foundry FQDN does not resolve privately.
# It falls through to the PUBLIC IP — silently bypassing your private endpoint:
$ nslookup my-aoai-prod.services.ai.azure.com
Non-authoritative answer:
Name: my-aoai-prod.services.ai.azure.com
Address: 20.42.65.92 <-- PUBLIC IP. Private Link is being bypassed.
$ nslookup my-aoai-prod.openai.azure.com
Name: my-aoai-prod.privatelink.openai.azure.com
Address: 10.0.2.4 <-- correct. The OLD zone still works.
# 3. Or, with public access disabled, the call simply dies:
curl: (28) Failed to connect to my-aoai-prod.services.ai.azure.com port 443:
Connection timed outSymptom: Existing openai.azure.com calls keep working, but every new Foundry capability (Agent Service, model catalog, Foundry API) fails to resolve or times out. Failure point: Client → Private DNS zone lookup → no zone exists for the new FQDN → public resolution or timeout. Default platform behaviour: The kind-flip is non-destructive and preserves your endpoint, keys, and existing zone. It does not create the two additional private DNS zones that Foundry's other two FQDNs require.
There is a particular kind of dread that comes from reading "Microsoft is automatically upgrading your resources" in a service notice, especially when those resources sit behind a private endpoint in a locked-down landing zone. The good news is that the auto-upgrade is more careful than the panic suggests — private-networked resources are explicitly held back from the first waves. The bad news is that this is a stay of execution, not a pardon: the same resources become eligible in a later wave, and the manual upgrade path that many teams are already taking has exactly the failure mode everyone fears. Either way, the fix is the same, it is cheap, and you can do it today, entirely ahead of time.
Azure OpenAI and Microsoft Foundry are not two different Azure resource types. They are the same resource type — Microsoft.CognitiveServices/accounts — distinguished by a single kind property. The "upgrade" is therefore not a migration in the traditional sense. Nothing is copied, moved, or recreated. One property mutates in place:
- kind changes from OpenAI to AIServices
- properties.allowProjectManagement is set to true
- A managed identity is configured on the resource
That is the whole operation. Because both variants share the same resource type and management APIs, your existing Azure RBAC assignments and Azure Policy controls continue to apply, and the upgrade preserves the resource name, endpoint, API keys, managed identity, security configurations, fine-tuning jobs, batches, stored completions, and files. Costs do not increase.
Because so much is preserved, teams reasonably conclude that nothing needs to change on their side. And for the existing Azure OpenAI endpoint, nothing does — it keeps resolving through your existing privatelink.openai.azure.com zone. The gap is invisible until someone tries to use a Foundry feature, at which point they hit an FQDN that your private DNS has never heard of.
An honest framing matters here, because there is a lot of alarmist commentary about this rollout. The kind-flip will not take your production GPT inference offline. Your existing endpoint, keys, and private DNS zone survive intact. What it will do is quietly leave every new Foundry capability unreachable over private networking — and, worse, resolve those FQDNs to public IPs, which means a client that can reach the internet will silently bypass your private endpoint entirely. That is a compliance problem before it is an availability problem.
Here is the detail that most coverage of this rollout gets wrong, and it changes your risk posture materially: resources using private networking are not selected for auto-upgrade in the current waves. Microsoft's auto-upgrade documentation defines an explicit status code for precisely this case.
Eligible Scheduled for auto-upgrade on the date in scheduledAt.
Completed Upgrade done. Resource is now Foundry. scheduledAt is null.
DeferredByCustomer You deferred it. scheduledAt is null.
RolledBack Upgraded, then rolled back to Azure OpenAI.
Failed: CustomerManagedKeys Not eligible — uses CMK, not in an allow-listed subscription.
Failed: PrivateNetworking Not yet eligible — uses private networking.
"Manually upgrade to configure two additionally
required DNS zones."
Failed: WeightsAndBiases Not eligible — W&B integration is unsupported on Foundry.So if your Azure OpenAI resource sits behind a private endpoint today, the platform is currently refusing to auto-flip it, and telling you why. That is a safety net — but read the wording carefully. The status is "not yet eligible." The documentation is explicit that the rollout is staged, that resources using security configurations such as private networking or CMK are simply not selected at first, and that once zero-touch support for those configurations becomes available, those resources can be selected later and return to Eligible with a new scheduled date.
Your actual exposure is therefore threefold:
- The manual upgrade, today. Plenty of teams are clicking the portal's upgrade banner right now to get Agent Service or the wider model catalog. That path has no private-networking guard rail — it is exactly where the DNS gap bites.
- A future auto-upgrade wave. When zero-touch support for private networking ships, your resource flips from Failed: PrivateNetworking back to Eligible with a scheduled date. You do get advance notice — but if your DNS zones are not already in place, you are now doing network changes against a clock.
- Drift between environments. Your dev resource has no private endpoint, so it is eligible and gets flipped automatically. Your production resource does not. You now have two resources of different kinds and a template that no longer matches reality.
Nothing is going to break your private-networked resource tonight. But the two DNS zones cost nothing to create, are harmless to have in place before you upgrade, and turn the eventual flip — whenever and however it happens — into a non-event. Create them now, on your own schedule, and the entire problem disappears. That is the rest of this guide.
Private Link works by overriding public DNS. When a client in your VNet resolves your resource's public hostname, a linked private DNS zone intercepts the lookup and returns the private endpoint's IP instead of the public one. No private zone, no interception — the client resolves the public IP and your private endpoint is bypassed.
The critical fact is that the private endpoint for Microsoft.CognitiveServices/accounts (subresource account) covers three public FQDNs, each with its own corresponding private DNS zone:
| Public FQDN | Required private DNS zone | Azure OpenAI | Foundry |
|---|---|---|---|
| openai.azure.com | privatelink.openai.azure.com | Required — you have this | Still used (existing endpoint) |
| cognitiveservices.azure.com | privatelink.cognitiveservices.azure.com | Often absent | Required |
| services.ai.azure.com | privatelink.services.ai.azure.com | Not used | Required |
An Azure OpenAI resource behind Private Link typically only ever needed the first zone, so that is the only one most landing zones created. After the flip, the resource answers on all three — but two of them have no private zone to resolve against. Those are the "two additionally required DNS zones" that Microsoft's own Failed: PrivateNetworking status message tells you to configure.
A recurring mistake when people try to "fix" this by hand: requests from clients must use the resource's public custom subdomain as the base URL (for example my-aoai-prod.services.ai.azure.com). Do not point clients at *.privatelink.services.ai.azure.com — that hostname is part of Azure's internal CNAME resolution chain, not a client-facing endpoint. Clients on the VNet use exactly the same connection string as public clients; the private DNS zone does the redirection invisibly.
If your VNet still has outbound internet access, a missing private zone does not produce a clean error. The client resolves services.ai.azure.com to a public IP and connects over the public internet — traffic that you believe is on the Azure backbone is not. Your security review says "Private Link"; your packets say otherwise. If public network access is disabled on the resource, you instead get an honest timeout. Perversely, the timeout is the better outcome.
Architectural Topology: Failing vs Remediated
| Component | Failing configuration (current) | Remediated configuration (fix) |
|---|---|---|
| Private DNS zones | Only privatelink.openai.azure.com | All three zones, each VNet-linked |
| DNS zone group | Single zone config on the private endpoint | Three FQDN configs in the endpoint's zone group |
| New Foundry FQDNs | Resolve to a public IP — Private Link silently bypassed | Resolve to the private endpoint IP |
| Upgrade trigger | Portal banner, clicked ad hoc by whoever saw it | Deliberate, template-driven, on your schedule |
| Auto-upgrade posture | Unmanaged — mode: Enabled by default | foundryAutoUpgrade.mode: Deferred until ready |
| Terraform provider | AzureRM ≤ 4.57.0 — plans a destroy/recreate | AzureRM > 4.57.0 — in-place, non-destructive update |
| IaC state | Template says kind: OpenAI; Azure says AIServices | Template is the source of truth for the flip |
Before changing anything, establish exactly where you stand: what kind is the resource, is it scheduled for auto-upgrade, and which of the three private DNS zones already exist and are linked to your VNet.
- Record the resource kind. OpenAI means not yet flipped; AIServices means it already happened — check your DNS immediately.
- Record the auto-upgrade status. Eligible with a scheduledAt date means you have a deadline. Defer it if you are not ready.
- Confirm the private endpoint IP so you can verify resolution against it later.
- List existing private DNS zones and their VNet links. A zone that exists but is not linked to the client's VNet is functionally the same as no zone at all.
- Check hub-and-spoke. In a hub-spoke topology the zones usually live in the hub — every spoke VNet that hosts clients must be linked, or use DNS forwarding.
This is the core fix, and the reassuring part is that it is safe to apply before you upgrade anything. Creating the two additional private DNS zones on a resource that is still kind: OpenAI is harmless — nothing resolves against them until the resource starts answering on those FQDNs. Deploy this today, and the flip becomes a non-event whenever it arrives.
You can create the A records manually, and in a heavily customized DNS estate you may have to. But wherever possible, attach the zones to the private endpoint's DNS zone group and let Azure create and maintain the records. Hand-written A records go stale the moment a private endpoint IP changes, and that failure is far harder to spot than a missing zone.
If you manage the resource with Terraform, there is a trap here that is far more dangerous than the DNS gap, and it deserves to be the loudest warning in this guide.
Microsoft's documentation is explicit: when using the AzureRM provider, you must use a version greater than 4.57.0 for a non-destructive resource update. On older provider versions, changing kind is treated as a ForceNew attribute — Terraform will plan to destroy and recreate the Cognitive Services account.
Destroying that account means destroying your model deployments, fine-tuned models, PTU reservations, stored completions, batches, and files. A "kind flip" turns into a data-loss incident. Always read the plan. If you see -/+ destroy and then create replacement, stop and upgrade the provider.
Apply the DNS zones first, confirm they exist and are linked, and only then flip the kind. Doing it in one apply usually works, but splitting it into two applies means that if the flip has a problem, your DNS is already correct and the rollback is trivial. There is no upside to coupling them.
If your resource shows "status": "Eligible" with a scheduledAt date and you are not ready — security review outstanding, DNS zones not deployed, change freeze in effect — you can defer. This is a supported, first-class operation, not a hack.
You can also defer in the portal: open the resource, select Resource upgrade in the left navigation, and choose Defer upgrade. After deferring, the status becomes DeferredByCustomer and scheduledAt becomes null.
Be honest with yourself about what deferring buys you: time, not permanence. The direction of travel is clear — Foundry is the consolidated resource, and the Assistants API has a hard retirement date. Use the deferral window to create the DNS zones, run your security review, and upgrade deliberately. Do not use it to do nothing for six months and then get surprised again.
The flip is reversible. If a resource was upgraded — automatically or by someone clicking the banner — and you need to return to Azure OpenAI, you can roll it back. But rollback is blocked by any Foundry-specific sub-resource that cannot exist on an Azure OpenAI account, and the error messages are not always obvious.
| Blocker / error | Why it blocks | Fix |
|---|---|---|
| Foundry projects exist | Projects are a Foundry-only construct | Delete all projects on the resource before rolling back |
| Connections exist | Foundry-only sub-resource | Delete connections before rolling back |
| Non-OpenAI model deployments | Azure OpenAI kind cannot host non-OpenAI models | Delete any non-OpenAI deployments (Llama, DeepSeek, etc.) |
| Azure OpenAI instance quota exceeded | Limit of 30 Azure OpenAI instances per subscription per region | Delete an unused Azure OpenAI resource, then retry the rollback |
| AIServices instance quota exceeded | Limit of 100 AIServices instances per subscription per region | Delete an unused Foundry resource, then retry the upgrade |
If you roll back to kind: OpenAI, do not tear down the two extra private DNS zones. They are inert on an Azure OpenAI resource — nothing resolves against them — and leaving them means the next upgrade attempt, whenever it comes, needs no network change at all. Deleting them just recreates the problem for your future self.
Validation & Verification: Confirm the Fix
The whole failure mode here is silent — a missing zone resolves to a public IP and everything appears to work. So validation cannot be "the app still runs." It has to be: does each of the three FQDNs resolve to the private endpoint IP, from inside the VNet? Run these from a VM or container in the client subnet, not from your laptop.
Resolving to a private IP proves the zone works. It does not prove your traffic is private, because a client with internet access will happily use a public route if DNS ever hands it one. The decisive test is the negative one: with public network access disabled on the resource, the same call from outside the VNet must fail. If it succeeds, you have a private endpoint that nothing is actually forced to use — which is the exact compliance gap the missing zones create in the first place.
Key Takeaways
Frequently Asked Questions
Related FAVRITE Articles
- How to Fix Azure OpenAI Token Limits: Architectural Patterns for High-Throughput Apps
- Fixing the First-Request Lag: Azure Functions and Container Apps for AI Microservices
- Azure Front Door Wildcard Certificate Revalidation Fix
- Secure Azure File Storage Architecture with Private Endpoints