Appearance
ADR-0004: Foundry resource topology and region
- Status: Accepted (owner approved 2026-07-24)
- Date: 2026-07-11
- Amended: 2026-08-02, capacity guidance superseded
Capacity amendment, 2026-08-02. The
--sku-capacity 1in the deployment command below is superseded. Capacity is now a per-model registry field (ADR-0018) and the live account runs real per-model capacities. Capacity 1 is not a cost control: it measures at roughly one request per minute whileGlobalStandardstill bills per token, so it breaks agentic callers without reducing spend. The topology and region decisions in this ADR are unchanged.
This ADR records a reusable topology-and-region decision for Azure AI Foundry builds on this platform. The concrete detail of the first proven build (real resource names, the legacy narrator Speech account, the chosen region, and the voice and style picks) is preserved under the "Worked example" section at the end, clearly separated from the reusable decision above it.
Context
The source plans and the environment check converge on a single shared resource, and the kind of resource is forced by the two models' access patterns. The forces, grounded in ai/verification/environment-readiness.md, docs/research/SPIKE-03-tenant-readiness.md, docs/research/SPIKE-04-identity-security.md, and docs/research/SPIKE-06-pipeline-integration.md:
- One kind serves both modalities. MAI-Image-2.5 is a Foundry model deployment (Global Standard, model format Microsoft) and therefore requires an
AIServices-kind account. MAI-Voice-2 has no deployment step at all; its prerequisite is simply a Speech resource in a supporting region, and voices are selected by name at synthesis time (for exampleen-US-<VoiceName>:MAI-Voice-2) in the SSML<voice>element. Because theAIServiceskind also serves the Speech surface, one resource can host the image deployment and serve the voice work, exactly as both plans proposed. - The existing legacy Speech account cannot host this. The build inherits an existing narrator Speech account of kind
SpeechServices(single-service) at the F0 tier, so it cannot take a Foundry model deployment, and F0 eligibility for MAI voices is unverified. A newAIServicesresource is required regardless of what any spike finds; this is confirmation, not new risk. - The narrator track stays where it is. The pipeline keeps the existing narrator and read-along audio on the current Speech resource (
AZURE_SPEECH_*), and points only the new MAI listen-voice variants and the image calls at the new resource (MAI_SPEECH_*,MAI_IMAGE_*). So the new resource is additive; it does not replace the legacy account. - Tier. S0 is required: F0 eligibility for MAI voices is undocumented, and the MAI meter has no documented free allotment. S0 also gives the higher Speech throughput (200 transactions per second default).
- Region. Choose the single region (per ADR-0001) that is on the seven-region MAI-Image-2.5 Global Standard list, is marked for MAI voices, and carries the Speech "voices and styles in preview" flag that the chosen expressive style relies on. That intersection resolves to one region for this model pair.
- Custom subdomain. An
AIServicesaccount is created with a custom subdomain by default; this is also the prerequisite for a later Microsoft Entra path on the Speech surface (ADR-0005), so it is kept. - Global Standard residency note. MAI-Image-2.5 deploys as Global Standard, so transient image processing may occur outside the chosen region, while any data stored at rest (including the abuse-monitoring store) stays in the customer-designated geography. TTS real-time synthesis stays in-region and stores nothing.
Decision
Provision one shared Azure AI Foundry resource, kind AIServices, SKU S0, in the single qualifying region, in one dedicated resource group. It hosts the MAI-Image-2.5 deployment and serves MAI-Voice-2 through its Speech endpoint. This one-resource topology is recorded per the owner-locked MASTER-PLAN target and is not reopened.
On that resource:
- Deploy MAI-Image-2.5 as Global Standard.
az cognitiveservices account deployment createwith--model-name "MAI-Image-2.5" --model-format Microsoft --model-version 2026-06-02 --sku-name GlobalStandard --sku-capacity 1, verifying the version string is still current at deploy time (see ADR-0001 follow-up). Image calls hit the resource endpointshttps://<resource>.services.ai.azure.com/mai/v1/images/generationsand/edits. - Serve MAI-Voice-2 with no deployment. Voices are selected by name in SSML against the resource's Speech synthesis endpoint. No model deployment, no Foundry project, and no per-voice provisioning is required for the voice path.
- Enable the custom subdomain (the
AIServicesdefault) and keep it, as a harmless prerequisite for a future Entra-for-Speech move.
Naming intent (exact CAF strings finalized in the design phase). One resource group and one Foundry account, named CAF-aligned and neutral to the initiative rather than to any consumer, because the resource is shared by all consumers and both modalities. The intended shape is a resource-type prefix, a brand-neutral initiative token (an approved short name for the media backbone), an environment token, the region token, and an instance index (for example a resource group like rg-<initiative>-<env>-<region>-01 and a Foundry account with the current CAF abbreviation for an Azure AI Foundry / AI Services account). The final resource-type abbreviations and token choices are confirmed against the naming standard in the design phase (governance MCP validate) before any create.
Do not reuse the existing legacy Speech account. The inherited F0 SpeechServices account keeps serving the narrator and read-along track; the new S0 AIServices resource serves the MAI listen voices and the image model.
Consequences
Positive:
- One resource means one resource group, one budget scope (ADR-0006), one identity and role surface (ADR-0005), and one set of secrets, which is the simplest posture for a multi-consumer, two-modality workload.
- The
AIServiceskind serves image and voice together, so no second resource is needed and the two source plans share infrastructure as designed. - The chosen region satisfies both models and the preview-styles flag, and co-locates with the existing Key Vault and Speech resource.
- The existing narrator and read-along pipeline is untouched, so read-along stays on the proven WordBoundary track while the MAI voices are added additively.
Negative:
- A new resource must be created (the existing F0 Speech account is deliberately not upgraded or reused), so there are now two Speech-capable resources in the subscription (the old narrator F0 and the new S0), and the pipeline carries a two-resource key split.
- Global Standard means transient image processing may leave the chosen region even though at-rest data stays in the customer-designated geography; acceptable for benign hand-drawn illustrated content but recorded for the record.
- One shared resource means Azure meters aggregate all consumers; per-consumer cost attribution comes from the pipeline ledger, not Azure tags (ADR-0006).
- Both models are preview; retention and residency findings are the documented steady state and should be re-verified at GA.
Follow-ups:
- Run the roughly 30-minute voice spike against the new resource before layering variant code: confirm whether MAI-Voice-2 emits usable WordBoundary events, whether
Audio48Khz96KBitRateMonoMp3is accepted (fall back toAudio24Khz160KBitRateMonoMp3if not), and read the exact regional voice id for any accented listen voice off the Foundry playground. - The design phase locks the final CAF names and decides whether to create the optional Foundry project (useful mainly for the playground audition).
- Deployment is gated on explicit owner confirmation per repo policy.
Alternatives considered
- Reuse the existing legacy Speech account (SpeechServices, F0). Rejected: wrong kind (a single-service Speech account cannot host a Foundry model deployment), and F0 eligibility for MAI voices is unverified with no documented free allotment.
- Two separate resources, one for image and one for voice. Rejected: the
AIServiceskind serves both, and one resource collapses identity, budget, and secret handling into a single surface; both plans and the environment check call for one shared resource. - A plain Speech resource (kind
SpeechServices, S0) for voice plus a separate Foundry resource for image. Rejected for the same reason: it defeats the shared-resource goal and doubles the operational surface for no benefit, sinceAIServicesalready includes Speech. - F0 tier. Rejected: MAI-voice F0 eligibility is undocumented and the MAI meter has no free allotment, so S0 is assumed and every MAI character and image is treated as billable.
- A region that does not satisfy all three constraints. Rejected here and in ADR-0001: the qualifying region must appear on the image model's Global Standard list, be marked for the voice model, and carry the preview-styles flag; a region missing any one of these (as the first build's nearest alternative region was) is rejected.
<!-- safety-scan-worked-example:start -->
Worked example: the Brand A and Brand B media backbone
Everything in this section is what was actually built with the reusable decision above, on the first proven build of this platform. It is historical fact, not part of the general methodology.
The first proven build stood up one shared media backbone for two publishing brands (Brand A and Brand B), each with its own reader app, served by a single AIServices resource.
- Shared resource:
aif-<workload>-<env>-<region>-01(AIServices, S0) in resource grouprg-<workload>-<env>-<region>-01, region East US. It hosts the MAI-Image-2.5 deployment (mai-image-25, Global Standard) and serves MAI-Voice-2 through its Speech endpoint. No deployment step exists for the voice path. - Legacy narrator account, left untouched: the legacy narrator Speech resource (in its own resource group), kind
SpeechServices, tier F0. It keeps serving the existing narrator and read-along track (AZURE_SPEECH_*), while the new resource serves only the MAI listen voices and image calls (MAI_SPEECH_*,MAI_IMAGE_*). The new resource is additive; it does not replace that legacy account. - Region: East US was the one region satisfying all three constraints (on the MAI-Image-2.5 Global Standard list, marked for MAI voices, and carrying the preview-styles flag).
eastus2did not offer MAI-Image-2.5, which is why it was rejected in ADR-0001. East US also co-located with the existing Key Vault and the legacy Speech resource. - Voice and style picks: the listen-voice set was Harper (en-US), Lisa (en-AU), and Ethan (en-US, rendered with the
excitedstyle); the SSML<voice>example above resolves to, for example,en-US-Harper:MAI-Voice-2. - Naming: the CAF names
rg-<workload>-<env>-<region>-01andaif-<workload>-<env>-<region>-01are neutral to both brands, because the one resource is shared across both brands and both modalities.
<!-- safety-scan-worked-example:end -->
Sources
ai/verification/environment-readiness.md(the existing legacy Speech account is SpeechServices F0 and cannot host the deployment; one resource can serve both; deployment command shape)docs/research/SPIKE-03-tenant-readiness.md(region and tier confirmation; the qualifying region satisfies both models)docs/research/SPIKE-04-identity-security.md(custom subdomain; Global Standard residency; no deploy step for voice)docs/research/SPIKE-06-pipeline-integration.md(two-resource key split; narrator stays on the existing resource; canvas sizes and endpoints)- Deploy and use MAI image models in Microsoft Foundry (Global Standard, endpoints, parameters, size cap): https://learn.microsoft.com/azure/foundry/foundry-models/how-to/use-foundry-models-mai
- What is MAI-Voice (preview)? (no deploy step; voice name in the SSML
<voice>element; region prerequisite): https://learn.microsoft.com/azure/ai-services/speech-service/mai-voices - Foundry Models sold by Azure (capability and size limits): https://learn.microsoft.com/azure/foundry/foundry-models/concepts/models-sold-directly-by-azure
- Data, privacy, and security for Models sold by Azure (Global processing location; at-rest data in the customer geography): https://learn.microsoft.com/azure/foundry/responsible-ai/openai/data-privacy