In Part 1 we provisioned a Foundry resource, deployed GPT-4.1 mini, and made our first API call from Python. The Bicep template was intentionally minimal โ public network, no RBAC, a single deployment type.

In production you need more. This article covers:
- Deployment types โ Global Standard vs Data Zone vs Regional and when to pick which
- Region selection โ how to choose where your Foundry resource lives
- Networking โ locking down access with private endpoints
- RBAC โ granting least-privilege access with Foundry roles
- Reusable Bicep modules โ structuring your IaC for multi-environment deployments
All code samples from this series are available in this repository (coming soon).
Deployment types explained #
When you deploy a model in Foundry, you pick a deployment type that controls three things: where data is processed, how you pay, and performance characteristics.
| Deployment type | SKU name in Bicep | Data processing | Billing | Best for |
|---|---|---|---|---|
| Global Standard | GlobalStandard | Any Azure region | Pay-per-token | General workloads, highest quota |
| Global Provisioned | GlobalProvisionedManaged | Any Azure region | Reserved PTU | Predictable high-throughput |
| Global Batch | GlobalBatch | Any Azure region | 50% discount | Large async jobs (24-hr target) |
| Data Zone Standard | DataZoneStandard | Within data zone (EU/US) | Pay-per-token | EU/US data residency compliance |
| Data Zone Provisioned | DataZoneProvisionedManaged | Within data zone (EU/US) | Reserved PTU | Data zone + predictable throughput |
| Standard (Regional) | Standard | Single region | Pay-per-token | Strict regional compliance, low volume |
| Regional Provisioned | ProvisionedManaged | Single region | Reserved PTU | Regional compliance + guaranteed throughput |
Full details: Deployment types for Microsoft Foundry Models
How to choose #
1 โโโโโโโโโโโโโโโโโโโโโโโ
2 โ Data residency โ
3 โ requirements? โ
4 โโโโโโโโฌโโโโโโโโโโโฌโโโโโ
5 โ โ
6 No limits EU/US only Single region
7 โ โ โ
8 โผ โผ โผ
9 Global * DataZone * Standard /
10 Regional Provisioned
11 โ โ
12 โโโโโโโโโโโโโโดโโโ โโโโโโดโโโโโโโโโ
13 โ โ โ โ
14 Variable Steady Variable Steady
15 traffic traffic traffic traffic
16 โ โ โ โ
17 โผ โผ โผ โผ
18 Global Global DataZone DataZone
19 Standard Provisioned Standard Provisioned
For our product description generator, Global Standard is the simplest starting point โ highest quota, widest model availability, pay-per-token. If you need EU data residency (e.g. GDPR), switch to DataZone Standard deployed in a European region.
Bicep: switching deployment types #
In Part 1 we used Standard. Here’s how to switch to GlobalStandard or DataZoneStandard:
1@description('Deployment type SKU')
2@allowed([
3 'Standard'
4 'GlobalStandard'
5 'DataZoneStandard'
6])
7param deploymentSku string = 'GlobalStandard'
8
9resource deployment 'Microsoft.CognitiveServices/accounts/deployments@2025-04-01-preview' = {
10 parent: foundry
11 name: modelName
12 sku: {
13 name: deploymentSku
14 capacity: modelCapacity
15 }
16 properties: {
17 model: {
18 name: modelName
19 format: 'OpenAI'
20 version: modelVersion
21 }
22 }
23}
Choosing a region #
Two factors matter:
- Latency to your users โ use Azure Speed Test to measure round-trip time from your location to candidate regions.
- Model availability โ not every model is available in every region. Check the region availability matrix before committing.
For Global Standard deployments, the region of your Foundry resource matters less (requests can be processed anywhere), but it still determines where data is stored at rest. For Standard (Regional) deployments, the region determines both storage and processing โ model availability is more limited.
Here’s a quick snapshot of GPT model availability across European regions for Standard (Regional) deployments:
| Model | France Central | Sweden Central | UK South | North Europe | West Europe |
|---|---|---|---|---|---|
| gpt-4.1 | โ | โ | โ | โ | โ |
| gpt-4.1-mini | โ | โ | โ | โ | โ |
| gpt-4o | โ | โ | โ | โ | โ |
| gpt-5.1 | โ | โ | โ | โ | โ |
Sweden Central has the broadest model selection in Europe for regional deployments. If you use Global Standard or Data Zone Standard, all major models are available regardless of resource region.
Bicep: parameterise the region #
1@description('Azure region for the Foundry resource')
2@allowed([
3 'swedencentral'
4 'francecentral'
5 'uksouth'
6 'eastus'
7 'eastus2'
8])
9param location string = 'swedencentral'
Locking down networking with private endpoints #
By default, Foundry resources are accessible from the public internet. In production, you should restrict access to your virtual network.
Architecture #
1โโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโ
2โ Your VNet (10.0.0.0/16) โ
3โ โโโโโโโโโโโโโโโโโโโโโโ โ
4โ โ Subnet: default โ โ
5โ โ 10.0.1.0/24 โ โ
6โ โ โโโโโโโโโโโโ โ โ
7โ โ โ Your App โโโโโโโโผโโโบ Private โ
8โ โ โโโโโโโโโโโโ โ Endpoint โ
9โ โโโโโโโโโโโโโโโโโโโโโโ (10.0.2.x) โ
10โ โโโโโโโโโโโโโโโโโโโโโโ โ โ
11โ โ Subnet: pe-subnet โ โ โ
12โ โ 10.0.2.0/24 โโโโโโโโโ โ
13โ โโโโโโโโโโโโโโโโโโโโโโ โ
14โโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโ
15 โ Private Link
16 โผ
17โโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโ
18โ Microsoft Foundry โ
19โ publicNetworkAccess: Disabled โ
20โโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโ
Bicep: VNet + Private Endpoint #
1@description('Enable private networking')
2param enablePrivateEndpoint bool = false
3
4// โโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโ
5// Virtual Network
6// โโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโ
7resource vnet 'Microsoft.Network/virtualNetworks@2024-05-01' = if (enablePrivateEndpoint) {
8 name: '${baseName}-vnet'
9 location: location
10 properties: {
11 addressSpace: {
12 addressPrefixes: ['10.0.0.0/16']
13 }
14 subnets: [
15 {
16 name: 'default'
17 properties: {
18 addressPrefix: '10.0.1.0/24'
19 }
20 }
21 {
22 name: 'pe-subnet'
23 properties: {
24 addressPrefix: '10.0.2.0/24'
25 }
26 }
27 ]
28 }
29}
30
31// โโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโ
32// Private Endpoint
33// โโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโ
34resource privateEndpoint 'Microsoft.Network/privateEndpoints@2024-05-01' = if (enablePrivateEndpoint) {
35 name: '${baseName}-pe'
36 location: location
37 properties: {
38 subnet: {
39 id: vnet.properties.subnets[1].id
40 }
41 privateLinkServiceConnections: [
42 {
43 name: '${baseName}-plsc'
44 properties: {
45 privateLinkServiceId: foundry.id
46 groupIds: ['account']
47 }
48 }
49 ]
50 }
51}
52
53// โโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโ
54// Private DNS Zone
55// โโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโ
56resource privateDnsZone 'Microsoft.Network/privateDnsZones@2024-06-01' = if (enablePrivateEndpoint) {
57 name: 'privatelink.cognitiveservices.azure.com'
58 location: 'global'
59}
60
61resource dnsZoneLink 'Microsoft.Network/privateDnsZones/virtualNetworkLinks@2024-06-01' = if (enablePrivateEndpoint) {
62 parent: privateDnsZone
63 name: '${baseName}-dns-link'
64 location: 'global'
65 properties: {
66 virtualNetwork: {
67 id: vnet.id
68 }
69 registrationEnabled: false
70 }
71}
72
73resource dnsZoneGroup 'Microsoft.Network/privateEndpoints/privateDnsZoneGroups@2024-05-01' = if (enablePrivateEndpoint) {
74 parent: privateEndpoint
75 name: 'default'
76 properties: {
77 privateDnsZoneConfigs: [
78 {
79 name: 'config'
80 properties: {
81 privateDnsZoneId: privateDnsZone.id
82 }
83 }
84 ]
85 }
86}
Then update the Foundry resource to disable public access when private endpoints are enabled:
1resource foundry 'Microsoft.CognitiveServices/accounts@2025-04-01-preview' = {
2 name: '${baseName}-ai'
3 location: location
4 kind: 'AIServices'
5 sku: {
6 name: 'S0'
7 }
8 identity: {
9 type: 'SystemAssigned'
10 }
11 properties: {
12 customSubDomainName: '${baseName}-ai'
13 allowProjectManagement: true
14 publicNetworkAccess: enablePrivateEndpoint ? 'Disabled' : 'Enabled'
15 }
16}
Deploy with private networking:
1az deployment group create \
2 --resource-group rg-foundry-demo \
3 --template-file main.bicep \
4 --parameters enablePrivateEndpoint=true
RBAC: least-privilege access #
Foundry introduces dedicated roles that map to common personas:
| Role | Role ID (GUID) | Who | Can do |
|---|---|---|---|
| Foundry Account Owner | e47c6f54-e4a2-4754-9501-8e0985b135e1 | Platform engineers | Full control over the Foundry resource and projects |
| Foundry Owner | c883944f-8b7b-4483-af10-35834be79c4a | Project leads | Manage a specific project โ models, agents, deployments |
| Foundry User | 53ca6127-db72-4b80-b1b0-d745d6d5456d | Developers | Use deployed models and agents, run experiments |
| Foundry Project Manager | eadc314b-1a2d-4efa-be10-5d325db5065e | Team managers | Manage project membership and settings |
Bicep: assign roles #
1@description('Principal ID of the developer who needs access')
2param developerPrincipalId string = ''
3
4// Foundry User role
5var foundryUserRoleId = '53ca6127-db72-4b80-b1b0-d745d6d5456d'
6
7resource roleAssignment 'Microsoft.Authorization/roleAssignments@2022-04-01' = if (!empty(developerPrincipalId)) {
8 name: guid(project.id, developerPrincipalId, foundryUserRoleId)
9 scope: project
10 properties: {
11 roleDefinitionId: subscriptionResourceId(
12 'Microsoft.Authorization/roleDefinitions',
13 foundryUserRoleId
14 )
15 principalId: developerPrincipalId
16 principalType: 'User'
17 }
18}
Deploy with RBAC:
1# Get your own principal ID
2MY_ID=$(az ad signed-in-user show --query id -o tsv)
3
4az deployment group create \
5 --resource-group rg-foundry-demo \
6 --template-file main.bicep \
7 --parameters developerPrincipalId=$MY_ID
Structuring Bicep for reuse #
As the template grows, split it into modules. Here’s a recommended structure:
1infra/
2โโโ main.bicep # Orchestrator
3โโโ main.bicepparam # Parameter file
4โโโ modules/
5โ โโโ foundry.bicep # Foundry resource + project
6โ โโโ model.bicep # Model deployment
7โ โโโ networking.bicep # VNet + Private Endpoint + DNS
8โ โโโ rbac.bicep # Role assignments
main.bicep (orchestrator) #
1targetScope = 'resourceGroup'
2
3param baseName string = 'foundry-demo'
4param location string = 'swedencentral'
5param modelName string = 'gpt-4.1-mini'
6param modelVersion string = '2025-04-14'
7param deploymentSku string = 'GlobalStandard'
8param modelCapacity int = 10
9param enablePrivateEndpoint bool = false
10param developerPrincipalId string = ''
11
12module foundryModule 'modules/foundry.bicep' = {
13 name: 'foundry'
14 params: {
15 baseName: baseName
16 location: location
17 enablePrivateEndpoint: enablePrivateEndpoint
18 }
19}
20
21module modelModule 'modules/model.bicep' = {
22 name: 'model'
23 params: {
24 foundryName: foundryModule.outputs.foundryName
25 modelName: modelName
26 modelVersion: modelVersion
27 deploymentSku: deploymentSku
28 modelCapacity: modelCapacity
29 }
30}
31
32module networkingModule 'modules/networking.bicep' = if (enablePrivateEndpoint) {
33 name: 'networking'
34 params: {
35 baseName: baseName
36 location: location
37 foundryId: foundryModule.outputs.foundryId
38 }
39}
40
41module rbacModule 'modules/rbac.bicep' = if (!empty(developerPrincipalId)) {
42 name: 'rbac'
43 params: {
44 projectId: foundryModule.outputs.projectId
45 developerPrincipalId: developerPrincipalId
46 }
47}
48
49output projectEndpoint string = foundryModule.outputs.projectEndpoint
Parameter file: main.bicepparam #
1using 'main.bicep'
2
3param baseName = 'foundry-demo'
4param location = 'swedencentral'
5param modelName = 'gpt-4.1-mini'
6param deploymentSku = 'GlobalStandard'
7param enablePrivateEndpoint = false
Deploy with the parameter file:
1az deployment group create \
2 --resource-group rg-foundry-demo \
3 --template-file infra/main.bicep \
4 --parameters infra/main.bicepparam
Restricting deployment types with Azure Policy #
If your organisation wants to enforce that only DataZoneStandard deployments are allowed (e.g. for GDPR), you can apply an Azure Policy:
1{
2 "mode": "All",
3 "policyRule": {
4 "if": {
5 "allOf": [
6 {
7 "field": "type",
8 "equals": "Microsoft.CognitiveServices/accounts/deployments"
9 },
10 {
11 "field": "Microsoft.CognitiveServices/accounts/deployments/sku.name",
12 "notIn": ["DataZoneStandard", "DataZoneProvisionedManaged"]
13 }
14 ]
15 },
16 "then": {
17 "effect": "deny"
18 }
19 }
20}
This prevents anyone from creating Global or Regional deployments โ only Data Zone SKUs are allowed.
Clean up #
1az group delete --name rg-foundry-demo --yes --no-wait
What’s next? #
In Part 3 we will explore the Foundry model catalog โ comparing GPT-4.1, GPT-5, and open-weight models โ benchmarks, pricing, and guidance on which model to pick for your use case.
Full series outline #
| # | Topic |
|---|---|
| 1 | Getting started โ Provision with Bicep, deploy GPT, generate descriptions |
| 2 | Bicep deep dive โ networking, RBAC, deployment types, region selection (this post) |
| 3 | Foundry model catalog โ comparing GPT-4.1, GPT-5, open-weight models and when to use what |
| 4 | Foundry services overview โ agents, Responses API, tools, memory and real-world use cases |
| 5 | Prompt engineering and structured JSON output for product descriptions |
| 6 | Building the Python API โ FastAPI backend with Foundry SDK |
| 7 | Adding a database โ product catalog with PostgreSQL and RAG via Azure AI Search |
| 8 | Content safety, guardrails and Responsible AI |
| 9 | Building the Vue.js frontend โ a full-stack product description generator |
| 10 | CI/CD with GitLab, cost optimization and monitoring |
Stay tuned!