July 9, 2026

Azure Bicep Fundamentals for Real Projects

Azure Bicep Fundamentals for Real Projects
Azure Bicep Fundamentals for Real Projects
M365 FM Podcast
Azure Bicep Fundamentals for Real Projects

Azure Bicep is Microsoft’s modern Infrastructure as Code (IaC) language for deploying Azure resources using a clean, declarative syntax. This episode explains why Bicep has become the preferred choice over traditional ARM templates and how it helps teams build repeatable, reliable, and maintainable cloud environments.

You'll learn the core building blocks of every Bicep project, including resources, parameters, variables, outputs, modules, conditions, and loops. The discussion also covers symbolic names, automatic dependency management, and how reusable modules simplify even large-scale Azure deployments.

Beyond the syntax, the episode focuses on practical implementation. It explains how to organize Bicep projects for real-world environments, separate configuration from infrastructure, and build templates that work consistently across development, test, and production. You'll also hear why version control, code reviews, parameter files, and modular design are essential for successful Infrastructure as Code adoption.

Whether you're an Azure administrator, cloud engineer, or DevOps professional, this episode provides the foundation needed to start building production-ready Azure deployments with confidence. Instead of clicking through the Azure portal, you'll discover how Bicep enables consistent, automated deployments that are easier to maintain, scale, and evolve as your cloud environment grows.

Apple Podcasts podcast player iconSpotify podcast player iconYoutube Music podcast player iconSpreaker podcast player iconPodchaser podcast player iconAmazon Music podcast player icon

Azure Bicep serves as a modern tool for deploying Azure resources, and understanding Azure Bicep Fundamentals is essential for maximizing its potential. Its design focuses on simplifying the development process, making it easier for you to manage cloud infrastructure. By leveraging architectural principles like simplified syntax, modular design, and automatic state management, Bicep stands out among other tools. Understanding these fundamentals is crucial for you to implement Azure Bicep effectively in real projects. With its full integration with Azure services, Bicep empowers you to create scalable and maintainable infrastructures that align with your organizational goals.

Key Takeaways

  • Azure Bicep simplifies the deployment of Azure resources with a user-friendly syntax, making it easier to read and write.
  • Modular design in Bicep allows you to break down infrastructure into reusable components, enhancing maintainability.
  • Automated dependency management in Bicep speeds up deployments and reduces the risk of errors compared to traditional ARM templates.
  • Integrating Azure Bicep with CI/CD pipelines automates provisioning, ensuring consistent infrastructure across environments.
  • Creating reusable modules in Bicep promotes code sharing, reduces duplication, and streamlines collaboration among teams.
  • Implement best practices like using Azure Key Vault for secrets and enforcing compliance with Azure Policy to enhance security.
  • Organizing Bicep files logically improves clarity and efficiency, making it easier to manage complex deployments.
  • Leverage loops and conditions in Bicep to dynamically generate resources, reducing code complexity and enhancing scalability.

Azure Bicep Overview

Azure Bicep Overview

Bicep vs. ARM Templates

Azure Bicep is an open-source project developed by Microsoft. It simplifies the writing of Azure Resource Manager (ARM) templates. With Bicep, you can create and manage Azure resources more efficiently. The primary purpose of Azure Bicep is to enhance the authoring experience and improve code maintainability. Here are some key use cases for Azure Bicep:

  • Infrastructure as Code (IaC): You can define your infrastructure using code, making it easier to manage and version.
  • Modular Development: Bicep allows you to break down your infrastructure into smaller, reusable components.
  • Code Reusability: You can create templates that can be reused across different projects.

Bicep offers a simpler syntax compared to traditional JSON-based ARM templates. This makes it easier to read and write. For example, Bicep files are less verbose, allowing for easier referencing of parameters and resources. Here are some significant differences between Bicep and ARM templates:

  1. User-Friendly Syntax: Bicep's syntax is more readable, which enhances the overall development experience.
  2. Modularity: Each Bicep file acts as a reusable module, unlike ARM templates, which can be cumbersome to manage.
  3. Scope Definitions: Bicep supports deploying resources at different levels, providing more flexibility than ARM templates.

The evolution from ARM templates to Azure Bicep has brought several improvements. Bicep automatically manages dependencies, allowing for faster parallel deployments. This contrasts with ARM templates, where you often need to manage dependencies manually. The table below summarizes some key differences:

FeatureAzure BicepARM Templates
SyntaxLess verbose, easier to readMore verbose, harder to follow
Error ReductionFewer errors due to readabilityMore prone to errors
Dependency ManagementHandles dependencies automaticallyManual dependency management
Deployment SpeedSupports parallel deploymentsSequential deployments
ReusabilityEnhanced through modulesLimited reusability

Enterprise users have reported significant benefits from transitioning to Azure Bicep. Many have experienced a reduction in engineering hours for template development, approximately 50%. Additionally, users have noted a complete elimination of customer engineering hours spent on fixing failed security controls. This transition has streamlined access to the latest template versions for over 1,100 users, facilitating easier updates.

Benefits of Azure Bicep Fundamentals

Simplified Syntax

One of the most significant advantages of Azure Bicep is its simplified syntax. Compared to traditional ARM templates, Bicep's syntax is more concise and easier to read. This reduction in complexity enhances readability, allowing you to create and manage Azure resources more efficiently. As a result, you can speed up the development process and improve collaboration among team members.

With Azure Bicep, you can focus on defining your infrastructure without getting bogged down by verbose syntax. This streamlined approach not only reduces development time but also minimizes the potential for errors. You can quickly grasp the structure of your Bicep files, making it easier to maintain and update your infrastructure as needed.

Governance and Compliance

Azure Bicep also plays a crucial role in governance and compliance. It provides several features that help you manage compliance effectively across your Azure environments. Here are some key governance capabilities:

  • You can create policy assignments using a Bicep file, which is essential for managing compliance.
  • The Azure governance design area outlines the necessary tools for cloud governance, compliance auditing, and automated guardrails.
  • Azure Policy can enforce company standards, ensuring that your resources comply with organizational requirements.

By leveraging these governance features, you can maintain control over your Azure resources while ensuring they align with your organization's compliance standards. The modularization capabilities of Azure Bicep further enhance governance. You can create reusable components that encapsulate intricate details, simplifying complex configurations. For instance, when deploying a web application, you can separate components like virtual machines, load balancers, and databases into distinct modules. This modular approach not only reduces the learning curve for non-experts but also allows for efficient deployment of complex infrastructure.

Getting Started with Bicep

Environment Setup

To start using Azure Bicep, you need to set up your development environment. Follow these steps to ensure you have everything you need:

  1. Install Azure Bicep software: This is essential for compiling your Bicep files into ARM templates.
  2. Install Azure CLI or Azure PowerShell module: These tools allow you to manage Azure resources and deploy your Bicep files.
  3. Install Visual Studio Code: This code editor is highly recommended for writing Bicep files. You should also install the Bicep extension for enhanced functionality.

Before you begin, make sure you have the following:

  • A personal computer with Visual Studio Code installed.
  • Git installed for version control.
  • Access to an Azure DevOps organization with project administrator role access.

Writing Your First Bicep File

Now that your environment is set up, you can start creating Azure Bicep files. Here’s a simple tutorial to guide you through the process:

  1. Create a resource group: Use the Azure CLI to create a resource group where your resources will reside. Run the following command:

    az group create --name ExampleGroup --location "Central US"
    
  2. Create a Bicep file: Open Visual Studio Code and create a new file named main.bicep. In this file, define the resources you want to deploy. For example, you can create a storage account with the following code:

    resource storageAccount 'Microsoft.Storage/storageAccounts@2021-04-01' = {
      name: 'examplestoracc'
      location: resourceGroup().location
      sku: {
        name: 'Standard_LRS'
      }
      kind: 'StorageV2'
    }
    
  3. Deploy the Bicep file: After saving your Bicep file, deploy it using the Azure CLI with this command:

    az deployment group create \
    --name ExampleDeployment \
    --resource-group ExampleGroup \
    --template-file main.bicep \
    --parameters storageAccountType=Standard_GRS
    
  4. Check the deployment status: Wait for the deployment to complete. You will see a message indicating success when the provisioning state is "Succeeded."

By following these steps, you can easily create a Bicep script and deploy resources in Azure. This process not only simplifies your workflow but also enhances your ability to manage cloud infrastructure effectively.

Practical Applications of Azure Bicep

Practical Applications of Azure Bicep

Deploying Azure Resources

Azure Bicep simplifies the deployment of Azure resources, making it an excellent choice for real-world applications. You can define complex multi-resource solutions with ease. For instance, Bicep allows you to create multiple instances of similar resources using loops and iterations. This capability reduces code duplication and enhances maintainability. The for expression in Bicep enables you to generate multiple resource instances from a single definition. This feature streamlines the process of creating similar resources, making your deployments more efficient.

When you deploy to Azure, you can manage various resources such as virtual machines, storage accounts, and databases. By using Bicep templates, you can ensure that your infrastructure is consistent and reliable. Here are some common scenarios where Azure Bicep shines:

  • Web Applications: Deploying a web application often requires multiple resources like app services, databases, and networking components. Bicep helps you manage these resources seamlessly.
  • Microservices Architectures: You can define and deploy microservices using Bicep, ensuring that each service has the necessary resources allocated.
  • Development Environments: Quickly set up development environments with all required resources, allowing your team to focus on coding rather than infrastructure setup.

CI/CD Integration

Integrating Azure Bicep with CI/CD pipelines enhances your deployment process. You can automate provisioning and ensure that your infrastructure remains consistent across environments. Here are some best practices for integrating Azure Bicep with CI/CD workflows:

  • Use YAML templates to improve consistency in deployments.
  • Express complexity effectively through templates.
  • Reduce manual errors by automating tasks.
  • Store templates in version control for better management.
  • Promote reusability of templates across different resources.

To set up your CI/CD pipeline, follow these steps:

  1. Create a new folder named pipelines in your repository.
  2. Define your BuildBicep task in the build automation script.
  3. Utilize Azure Pipelines agents to run your PowerShell scripts.

Building security and compliance into your CI/CD pipelines means catching problems before they reach production. This proactive approach saves time and resources. Additionally, integrating Azure Verified Modules (AVM) with your workflows enhances modularity and reusability. This strategy streamlines the deployment process and ensures compliance with best practices.

By leveraging Azure Bicep in your CI/CD pipelines, you can automate the deployment of Bicep templates efficiently. This integration not only simplifies your workflow but also helps you manage your cloud infrastructure effectively.

Best Practices for Bicep

Organizing Bicep Files

Organizing your Bicep files effectively is crucial for maintaining clarity and efficiency in your projects. Here are some strategies to help you structure your Bicep files:

  • Use modules to encapsulate complexity and improve reuse.
  • Implement parameter files as environment contracts to define differences across environments.
  • Organize Bicep files to support multi-scope deployments effectively.
  • Integrate CI/CD pipelines to ensure quality and confidence in deployments.

By following these practices, you can enhance the maintainability and scalability of your Azure Bicep projects. A logical organization of your Bicep files promotes consistency and reduces duplication. This modular approach allows you to create reusable modules, simplifying maintenance and scaling. Additionally, Bicep's concise and readable format reduces complexity compared to traditional ARM templates. This reduction in complexity lowers friction in code reviews and day-to-day maintenance.

Creating Reusable Modules

Creating reusable modules in Azure Bicep offers numerous benefits. Here’s why you should focus on developing these self-contained units of infrastructure:

  • Reusable modules allow you to share code across multiple deployments, saving time and ensuring consistency.
  • They improve the readability of Bicep files by encapsulating complex deployment details.
  • Teams can create components once and use them multiple times, reducing duplication of effort.
  • Updating a module in one location benefits all implementations, streamlining collaboration.
  • Different teams can work on separate modules simultaneously, enhancing teamwork and efficiency.

By leveraging reusable modules, you can standardize your building blocks, reducing the chances of errors and promoting consistency across projects. This practice not only simplifies your workflow but also fosters collaboration among development teams. As you create Bicep templates, remember that the goal is to build a maintainable and scalable infrastructure that meets your organization's needs.

Common Pitfalls in Bicep

Misconfigurations

When working with Azure Bicep, you may encounter several common misconfigurations that can lead to deployment issues. Here are some pitfalls to watch out for:

  1. Leaving secrets in source control
  2. Not securing inputs properly
  3. Exposing secrets in outputs
  4. Weak or default naming conventions
  5. Not validating parameters
  6. Over-permissive role assignments
  7. Skipping policy enforcement

These misconfigurations can compromise the security and functionality of your resources. To avoid these issues, consider implementing the following best practices:

  1. Avoid Hardcoded Secrets: Use Azure Key Vault to securely store and retrieve sensitive information instead of embedding them in Bicep files.
  2. Use Managed Identities: Implement System-assigned Managed Identities for secure authentication, eliminating the need for storing credentials in code.
  3. Implement Role-Based Access Control (RBAC): Grant least privileges based on roles to ensure that only necessary permissions are given for specific tasks.
  4. Use Private Endpoints: Minimize exposure by using Private Endpoints for services like Storage Accounts and SQL Databases instead of public IPs.
  5. Enable Encryption at Rest: Utilize Customer-Managed Keys (CMK) for greater control over encryption rather than relying on platform-managed keys.
  6. Enable Diagnostic Logging: Use Azure Monitor to track activities and detect suspicious behavior through logging.
  7. Enforce Compliance with Azure Policy: Ensure that all deployments adhere to compliance requirements using Azure Policy.

By following these practices, you can significantly reduce the risk of misconfigurations in your Bicep deployments.

Resource Dependencies

Managing resource dependencies effectively is crucial when using Azure Bicep. Unlike ARM templates, where you often specify dependencies manually, Bicep automatically identifies many implicit dependencies. This automation simplifies deployment and reduces the chances of errors related to deployment sequencing.

To manage resource dependencies in your Bicep files, consider these best practices:

  1. Use symbolic names to create implicit dependencies instead of relying on explicit dependencies with dependsOn.
  2. Avoid using the reference and resourceId functions; instead, access resources by their symbolic names.
  3. Utilize the existing keyword to reference resources not deployed in the Bicep file.
  4. Limit nesting to improve code readability.
  5. Use the parent property or nesting for child resources instead of constructing resource names.
  6. Be cautious with dependsOn; unnecessary dependencies can slow down deployment and complicate resource management.
  7. Explicit dependencies should be rare; strive to use symbolic names to imply relationships.

By following these guidelines, you can enhance the clarity and efficiency of your Bicep templates, ensuring smoother deployments and better resource management.


In this blog, you explored the essentials of Azure Bicep fundamentals. You learned how Bicep simplifies the deployment of Azure resources through its cleaner syntax and modular design. Key takeaways include:

  1. Create a simple network stack by deploying a VNet, Subnet, and NSG.
  2. Introduce modularization by moving resources into separate Bicep modules.
  3. Use loops and conditions to dynamically generate multiple subnets.

Mastering these concepts will lead to more efficient and scalable cloud infrastructure. As you implement Azure Bicep in your projects, remember to validate and secure your templates. Embrace the future of cloud deployment with Azure Bicep, and leverage its capabilities to enhance your infrastructure management.

The ease of use, immediate support for new Azure features, and integration with CI/CD practices are driving its adoption.

FAQ

What is Azure Bicep?

Azure Bicep is a domain-specific language for deploying Azure resources. It simplifies the authoring experience compared to traditional ARM templates, allowing you to define infrastructure as code with a more readable syntax.

How do I install Azure Bicep?

You can install Azure Bicep using the Azure CLI or by downloading the Bicep CLI directly. Ensure you have the Azure CLI installed, then run the command: az bicep install.

Can I use Bicep with existing ARM templates?

Yes, you can integrate Bicep with existing ARM templates. You can reference ARM templates within Bicep files, allowing you to gradually transition to Bicep while maintaining your current infrastructure.

What are Bicep modules?

Bicep modules are reusable components that encapsulate specific resources or configurations. You can create modules to simplify complex deployments, promote code reuse, and enhance maintainability across your projects.

How does Bicep handle resource dependencies?

Bicep automatically manages resource dependencies. It identifies implicit dependencies based on resource references, reducing the need for manual dependency management and ensuring smoother deployments.

Is Bicep suitable for large-scale deployments?

Absolutely! Bicep is designed for scalability. Its modular approach allows you to manage large infrastructures efficiently, making it easier to maintain and update your deployments as your organization grows.

Can I use Bicep in CI/CD pipelines?

Yes, you can integrate Bicep into CI/CD pipelines. Automate your deployments by using Bicep templates in your pipeline scripts, ensuring consistent and reliable infrastructure provisioning across environments.

Where can I find more resources on Azure Bicep?

You can find additional resources on Azure Bicep in the official Microsoft documentation, GitHub repository, and community forums. These platforms offer tutorials, examples, and best practices to enhance your learning experience.

🚀 Want to be part of m365.fm?

Then stop just listening… and start showing up.

👉 Connect with me on LinkedIn and let’s make something happen:

  • 🎙️ Be a podcast guest and share your story
  • 🎧 Host your own episode (yes, seriously)
  • 💡 Pitch topics the community actually wants to hear
  • 🌍 Build your personal brand in the Microsoft 365 space

This isn’t just a podcast — it’s a platform for people who take action.

🔥 Most people wait. The best ones don’t.

👉 Connect with me on LinkedIn and send me a message:
"I want in"

Let’s build something awesome 👊

1
00:00:00,000 --> 00:00:03,260
The hobbyist deploys resources, the architect governs infrastructure.

2
00:00:03,260 --> 00:00:03,940
That's the line.

3
00:00:03,940 --> 00:00:04,860
That's where it splits.

4
00:00:04,860 --> 00:00:08,020
Most bicep files you see are just click next, translated to code.

5
00:00:08,020 --> 00:00:10,680
Someone took a portal workflow, wrote it in syntax form,

6
00:00:10,680 --> 00:00:12,540
and called it infrastructure as code.

7
00:00:12,540 --> 00:00:13,040
But it's not.

8
00:00:13,040 --> 00:00:14,740
It's automation, not architecture.

9
00:00:14,740 --> 00:00:16,300
Enterprise bicep is different.

10
00:00:16,300 --> 00:00:18,780
It's about life cycle, ownership, and predictability.

11
00:00:18,780 --> 00:00:21,240
Three separating principles drive the difference.

12
00:00:21,240 --> 00:00:24,660
Scope above subscriptions, contracts enforced in code,

13
00:00:24,660 --> 00:00:26,940
and state manage as a first class concern.

14
00:00:26,940 --> 00:00:28,900
What you're actually building isn't a template.

15
00:00:28,900 --> 00:00:31,640
It's a blueprint that survives organizational change.

16
00:00:31,640 --> 00:00:33,620
It's the thing that remains true when people leave,

17
00:00:33,620 --> 00:00:36,400
when teams restructure, when business priorities shift.

18
00:00:36,400 --> 00:00:38,740
That's the architecture question we're answering today.

19
00:00:38,740 --> 00:00:41,080
Why bicep isn't just armed with better syntax?

20
00:00:41,080 --> 00:00:42,280
Arm templates are powerful.

21
00:00:42,280 --> 00:00:43,620
They're also verbose.

22
00:00:43,620 --> 00:00:44,880
Dense JSON.

23
00:00:44,880 --> 00:00:46,320
Nested quotation marks.

24
00:00:46,320 --> 00:00:47,320
Escape characters.

25
00:00:47,320 --> 00:00:50,320
Long property names repeated across every resource definition.

26
00:00:50,320 --> 00:00:53,620
bicep strips that ceremony, shorter syntax, better readability,

27
00:00:53,620 --> 00:00:56,440
modules, parameters with constraints, variables.

28
00:00:56,440 --> 00:00:58,460
All of that makes bicep easier to write,

29
00:00:58,460 --> 00:01:01,180
easier to maintain, easier to share with teams.

30
00:01:01,180 --> 00:01:03,420
But here's where most conversations about bicep stop.

31
00:01:03,420 --> 00:01:04,620
And here's where they get it wrong.

32
00:01:04,620 --> 00:01:08,140
Microsoft isn't positioning bicep as better arm syntax

33
00:01:08,140 --> 00:01:09,720
because they want prettier JSON.

34
00:01:09,720 --> 00:01:10,780
That's not the strategy.

35
00:01:10,780 --> 00:01:12,300
The real shift is this.

36
00:01:12,300 --> 00:01:15,180
bicep is now the vehicle for infrastructure as policy.

37
00:01:15,180 --> 00:01:17,780
Deployment stacks introduce state awareness.

38
00:01:17,780 --> 00:01:19,620
You're no longer just tracking deployment history.

39
00:01:19,620 --> 00:01:20,980
You're tracking resource ownership.

40
00:01:20,980 --> 00:01:22,660
You're managing life cycle.

41
00:01:22,660 --> 00:01:24,740
When a resource disappears from your template,

42
00:01:24,740 --> 00:01:26,300
the system knows what to do.

43
00:01:26,300 --> 00:01:28,560
Delete it, detach it, or leave it alone.

44
00:01:28,560 --> 00:01:30,220
That's not syntax improvement.

45
00:01:30,220 --> 00:01:32,620
That's a fundamental change in how infrastructure relates

46
00:01:32,620 --> 00:01:33,580
to governance.

47
00:01:33,580 --> 00:01:35,860
Management groups scope used to be optional.

48
00:01:35,860 --> 00:01:37,340
Nice to have for large organizations.

49
00:01:37,340 --> 00:01:38,220
Now it's foundational.

50
00:01:38,220 --> 00:01:40,980
You deploy policy definitions at the management group level.

51
00:01:40,980 --> 00:01:43,500
You assign initiatives to hierarchies of subscriptions.

52
00:01:43,500 --> 00:01:45,540
You codify role-based access control.

53
00:01:45,540 --> 00:01:47,620
You're not just deploying resources anymore.

54
00:01:47,620 --> 00:01:50,260
You're defining organizational control planes.

55
00:01:50,260 --> 00:01:51,940
As your verified modules standardize

56
00:01:51,940 --> 00:01:53,300
what a good module looks like.

57
00:01:53,300 --> 00:01:55,500
And they do this across both bicep and terraform.

58
00:01:55,500 --> 00:01:57,700
This matters because it means your architectural standards

59
00:01:57,700 --> 00:01:59,420
aren't locked to one language.

60
00:01:59,420 --> 00:02:00,980
You're building a governance model that

61
00:02:00,980 --> 00:02:04,100
can move between tools without changing its shape.

62
00:02:04,100 --> 00:02:05,660
The implication is significant.

63
00:02:05,660 --> 00:02:07,780
Infrastructure code is no longer optional.

64
00:02:07,780 --> 00:02:09,020
It's the control plane itself.

65
00:02:09,020 --> 00:02:10,820
This changes how you think about modules.

66
00:02:10,820 --> 00:02:13,580
A module isn't just a reusable template anymore.

67
00:02:13,580 --> 00:02:14,380
It's a contract.

68
00:02:14,380 --> 00:02:17,700
It encodes organizational decisions, security baselines,

69
00:02:17,700 --> 00:02:20,500
naming conventions, compliance requirements.

70
00:02:20,500 --> 00:02:21,940
Everything your organization decided

71
00:02:21,940 --> 00:02:23,700
matters about how infrastructure should look.

72
00:02:23,700 --> 00:02:24,940
That's in the code now.

73
00:02:24,940 --> 00:02:26,820
It changes how you think about scope.

74
00:02:26,820 --> 00:02:29,260
You're not choosing between resource group, subscription,

75
00:02:29,260 --> 00:02:31,140
and management group based on convenience.

76
00:02:31,140 --> 00:02:33,060
You're choosing based on governance boundaries.

77
00:02:33,060 --> 00:02:36,460
Does this policy apply to one team or to the entire organization?

78
00:02:36,460 --> 00:02:38,020
That answer determines your scope.

79
00:02:38,020 --> 00:02:39,740
It changes how you think about lifecycle.

80
00:02:39,740 --> 00:02:41,980
Bicep deployments used to be fire and forget.

81
00:02:41,980 --> 00:02:44,580
Deploy the template, get the resources, move on.

82
00:02:44,580 --> 00:02:47,220
Now you're managing the full lifecycle of those resources

83
00:02:47,220 --> 00:02:48,140
as a unit.

84
00:02:48,140 --> 00:02:50,980
Updates, tear downs, ownership tracking, all of it

85
00:02:50,980 --> 00:02:52,300
coordinated through code.

86
00:02:52,300 --> 00:02:54,100
The distinction matters because it reshapes

87
00:02:54,100 --> 00:02:55,340
everything downstream.

88
00:02:55,340 --> 00:02:57,620
Your module design, your parameter strategy,

89
00:02:57,620 --> 00:03:00,060
your access controls, your CI/CD pipeline,

90
00:03:00,060 --> 00:03:02,820
your organizational structure around who approves what.

91
00:03:02,820 --> 00:03:05,340
Understanding this distinction requires looking at what

92
00:03:05,340 --> 00:03:07,180
actually changed in the Azure platform.

93
00:03:07,180 --> 00:03:08,900
And that's where we're going next.

94
00:03:08,900 --> 00:03:11,460
The new model, what changed in 2026?

95
00:03:11,460 --> 00:03:12,780
Here's the inflection point.

96
00:03:12,780 --> 00:03:14,220
This is where abstract architecture

97
00:03:14,220 --> 00:03:15,780
becomes concrete practice.

98
00:03:15,780 --> 00:03:17,980
In July, 2026, Azure Blueprints are gone.

99
00:03:17,980 --> 00:03:19,100
That's not a soft deprecation.

100
00:03:19,100 --> 00:03:20,220
That's the end of a service.

101
00:03:20,220 --> 00:03:21,660
Blueprints were Microsoft's attempt

102
00:03:21,660 --> 00:03:23,900
at a unified governance and deployment model.

103
00:03:23,900 --> 00:03:26,140
They bundled templates, policies, and role assignments

104
00:03:26,140 --> 00:03:27,620
into a single artifact.

105
00:03:27,620 --> 00:03:28,620
But they had limitations.

106
00:03:28,620 --> 00:03:30,260
They couldn't manage resource lifecycle.

107
00:03:30,260 --> 00:03:32,300
Clearly, they didn't track ownership at scale.

108
00:03:32,300 --> 00:03:34,020
They didn't integrate deeply enough

109
00:03:34,020 --> 00:03:36,460
with the organizational hierarchy of management groups.

110
00:03:36,460 --> 00:03:38,540
Deployment stacks are the successor.

111
00:03:38,540 --> 00:03:40,140
And they're not just a replacement.

112
00:03:40,140 --> 00:03:43,020
They're a rethinking of what it means to own infrastructure.

113
00:03:43,020 --> 00:03:45,540
Before stacks, your bicep deployment was a one-time event.

114
00:03:45,540 --> 00:03:46,740
You ran the template.

115
00:03:46,740 --> 00:03:48,020
Resources got created.

116
00:03:48,020 --> 00:03:49,700
Azure forgot about the relationship.

117
00:03:49,700 --> 00:03:51,500
If you modified the template three months later

118
00:03:51,500 --> 00:03:53,860
and redeployed, Azure didn't know which resources

119
00:03:53,860 --> 00:03:56,020
belonged to this deployment in which were orphaned.

120
00:03:56,020 --> 00:03:57,420
You had to manage that yourself.

121
00:03:57,420 --> 00:03:58,860
Stacks changed the model.

122
00:03:58,860 --> 00:04:00,700
A stack is an Azure resource.

123
00:04:00,700 --> 00:04:03,260
Microsoft resources deployment stacks

124
00:04:03,260 --> 00:04:04,620
that wraps your bicep template

125
00:04:04,620 --> 00:04:07,660
and maintains a persistent record of what it owns.

126
00:04:07,660 --> 00:04:10,060
When you update a stack, Azure compares the new template

127
00:04:10,060 --> 00:04:10,900
to the old one.

128
00:04:10,900 --> 00:04:12,220
It knows which resources are new.

129
00:04:12,220 --> 00:04:13,780
It knows which have been removed.

130
00:04:13,780 --> 00:04:15,660
And it knows exactly what to do about it.

131
00:04:15,660 --> 00:04:18,220
Delete them, detach them, or leave them alone.

132
00:04:18,220 --> 00:04:19,100
That's a state model.

133
00:04:19,100 --> 00:04:20,740
It's how Terraform has always worked.

134
00:04:20,740 --> 00:04:22,140
Now it's native to Azure.

135
00:04:22,140 --> 00:04:23,540
This matters operationally.

136
00:04:23,540 --> 00:04:26,460
It means environment life cycle becomes predictable.

137
00:04:26,460 --> 00:04:28,340
Spin up a dev environment in the morning,

138
00:04:28,340 --> 00:04:30,020
tear it down at night, completely,

139
00:04:30,020 --> 00:04:31,580
automatically without worrying about

140
00:04:31,580 --> 00:04:33,900
orphaned resources or cascading failures.

141
00:04:33,900 --> 00:04:34,980
In a brownfield migration,

142
00:04:34,980 --> 00:04:36,380
you can gradually move resources

143
00:04:36,380 --> 00:04:38,420
under stack management without breaking production.

144
00:04:38,420 --> 00:04:39,500
In a production update,

145
00:04:39,500 --> 00:04:41,620
you can remove a resource from your template

146
00:04:41,620 --> 00:04:43,300
and be confident it will be cleaned up

147
00:04:43,300 --> 00:04:45,260
in a controlled, auditable way.

148
00:04:45,260 --> 00:04:47,420
Management Group scope, which we touched on earlier,

149
00:04:47,420 --> 00:04:49,100
is now the entry point for everything

150
00:04:49,100 --> 00:04:50,700
that touches organizational control.

151
00:04:50,700 --> 00:04:52,180
You're not just deploying resources

152
00:04:52,180 --> 00:04:53,340
at the management group level.

153
00:04:53,340 --> 00:04:54,460
You're codifying policy.

154
00:04:54,460 --> 00:04:55,500
You're assigning roles.

155
00:04:55,500 --> 00:04:57,180
You're saying, this is how governance works

156
00:04:57,180 --> 00:04:59,500
in our organization and it lives in code.

157
00:04:59,500 --> 00:05:02,020
Azure verified modules have evolved too.

158
00:05:02,020 --> 00:05:03,860
They're not just bicep modules anymore.

159
00:05:03,860 --> 00:05:05,140
There are shared specification

160
00:05:05,140 --> 00:05:07,380
that applies to both bicep and Terraform.

161
00:05:07,380 --> 00:05:09,340
Same naming, same parameter structure,

162
00:05:09,340 --> 00:05:12,060
same security defaults, same testing requirements.

163
00:05:12,060 --> 00:05:13,580
This convergence is deliberate.

164
00:05:13,580 --> 00:05:15,180
It means you're not building an architecture

165
00:05:15,180 --> 00:05:16,420
locked to one language.

166
00:05:16,420 --> 00:05:17,580
You're building standards

167
00:05:17,580 --> 00:05:19,700
that can survive technology transitions.

168
00:05:19,700 --> 00:05:22,620
The implication sinks deeper than it first appears.

169
00:05:23,380 --> 00:05:25,300
Infrastructure code isn't an alternative

170
00:05:25,300 --> 00:05:26,740
to clicking the portal anymore.

171
00:05:26,740 --> 00:05:28,300
It's not a faster deployment option.

172
00:05:28,300 --> 00:05:29,980
It's become the control plane itself.

173
00:05:29,980 --> 00:05:32,260
This shifts into three concrete changes

174
00:05:32,260 --> 00:05:35,620
that separate the 2026 model from what came before.

175
00:05:35,620 --> 00:05:38,380
First, lifecycle management resources are no longer fire

176
00:05:38,380 --> 00:05:40,860
and forget they have ownership tracked in code.

177
00:05:40,860 --> 00:05:43,580
They have defined behavior when they no longer needed.

178
00:05:43,580 --> 00:05:45,620
Second, contract enforcement.

179
00:05:45,620 --> 00:05:47,700
Modules don't just encapsulate resources.

180
00:05:47,700 --> 00:05:49,700
They encapsulate organizational decisions,

181
00:05:49,700 --> 00:05:51,700
security baselines, naming standards,

182
00:05:51,700 --> 00:05:52,940
compliance requirements.

183
00:05:52,940 --> 00:05:54,900
All of it baked into the code as constraints,

184
00:05:54,900 --> 00:05:56,180
not suggestions.

185
00:05:56,180 --> 00:05:57,900
Third, governance as code.

186
00:05:57,900 --> 00:05:59,900
Policies don't live in an external system.

187
00:05:59,900 --> 00:06:01,420
They live in your bicep definitions.

188
00:06:01,420 --> 00:06:03,100
Roll assignments are versioned in Git.

189
00:06:03,100 --> 00:06:05,900
Policy initiatives cascade through management group hierarchies

190
00:06:05,900 --> 00:06:07,020
defined in code.

191
00:06:07,020 --> 00:06:08,460
Governance is infrastructure now.

192
00:06:08,460 --> 00:06:09,900
These aren't incremental improvements.

193
00:06:09,900 --> 00:06:11,300
They're architectural shifts.

194
00:06:11,300 --> 00:06:13,180
And understanding them requires grounding this

195
00:06:13,180 --> 00:06:14,860
in the actual decisions you have to make

196
00:06:14,860 --> 00:06:16,780
when you start building.

197
00:06:16,780 --> 00:06:18,140
The scope problem.

198
00:06:18,140 --> 00:06:19,940
Why subscriptions aren't enough?

199
00:06:19,940 --> 00:06:21,740
OK, so here's the first decision you make

200
00:06:21,740 --> 00:06:23,260
when you write a bicep file.

201
00:06:23,260 --> 00:06:24,540
Where does this code live?

202
00:06:24,540 --> 00:06:25,780
What scope are you targeting?

203
00:06:25,780 --> 00:06:28,100
Most organizations started resource group scope.

204
00:06:28,100 --> 00:06:29,060
It's the natural place.

205
00:06:29,060 --> 00:06:30,460
You've got a resource group.

206
00:06:30,460 --> 00:06:32,700
You want to deploy some storage accounts, some networks,

207
00:06:32,700 --> 00:06:34,180
some compute into that group.

208
00:06:34,180 --> 00:06:35,020
The scope is clear.

209
00:06:35,020 --> 00:06:36,140
The boundaries are obvious.

210
00:06:36,140 --> 00:06:37,700
The blast radius is contained.

211
00:06:37,700 --> 00:06:40,140
A broken template messes up one team's resources.

212
00:06:40,140 --> 00:06:41,380
Not the whole organization.

213
00:06:41,380 --> 00:06:42,380
It feels safe.

214
00:06:42,380 --> 00:06:44,140
And for small projects, it is safe.

215
00:06:44,140 --> 00:06:45,900
But watch what happens as you scale.

216
00:06:45,900 --> 00:06:47,940
You're not deploying to one resource group anymore.

217
00:06:47,940 --> 00:06:50,140
You're deploying to 10, then 50, then 100.

218
00:06:50,140 --> 00:06:52,980
You've got environments, dev, tests, staging, production,

219
00:06:52,980 --> 00:06:54,660
each one with its own resource group.

220
00:06:54,660 --> 00:06:58,100
Then you've got regional variants, US resources, EU resources.

221
00:06:58,100 --> 00:07:00,700
Then you've got teams, platform team, application team,

222
00:07:00,700 --> 00:07:03,580
security teams, each managing their own collections

223
00:07:03,580 --> 00:07:04,700
of resource groups.

224
00:07:04,700 --> 00:07:06,020
Now ask a simple question.

225
00:07:06,020 --> 00:07:07,460
Who owns that subscription?

226
00:07:07,460 --> 00:07:08,940
Not who has contributor access.

227
00:07:08,940 --> 00:07:09,820
Who actually owns it?

228
00:07:09,820 --> 00:07:11,060
Who makes decisions about it?

229
00:07:11,060 --> 00:07:13,700
Who updates the billing account if the credit card expires?

230
00:07:13,700 --> 00:07:15,460
Who says yes or no to a new policy?

231
00:07:15,460 --> 00:07:17,700
And who decides if the subscription gets decommissioned?

232
00:07:17,700 --> 00:07:19,780
In small organizations, that's easy to answer.

233
00:07:19,780 --> 00:07:21,620
In medium organizations, it's getting fuzzy.

234
00:07:21,620 --> 00:07:23,100
In large enterprises, it's chaos.

235
00:07:23,100 --> 00:07:26,020
You've got subscriptions that no one person can fully describe.

236
00:07:26,020 --> 00:07:27,900
They've accumulated resources over years.

237
00:07:27,900 --> 00:07:29,900
Policies that were added never removed.

238
00:07:29,900 --> 00:07:32,300
Roll assignments that predate half the current team.

239
00:07:32,300 --> 00:07:35,380
Someone left, but their service principle is still being used.

240
00:07:35,380 --> 00:07:37,100
And here's the architectural problem.

241
00:07:37,100 --> 00:07:40,260
Subscription scope is where the real governance questions live.

242
00:07:40,260 --> 00:07:42,820
Not the, does this template have the right network configuration

243
00:07:42,820 --> 00:07:43,700
questions?

244
00:07:43,700 --> 00:07:47,820
The who decides what policies apply to this entire Cloud footprint questions?

245
00:07:47,820 --> 00:07:50,380
That's where management groups scope enters the picture.

246
00:07:50,380 --> 00:07:52,180
Management groups sit above subscriptions.

247
00:07:52,180 --> 00:07:54,380
They're a tier of the hierarchy you don't typically see

248
00:07:54,380 --> 00:07:56,060
unless you're thinking architecturally

249
00:07:56,060 --> 00:07:57,580
about how your cloud is organized.

250
00:07:57,580 --> 00:07:58,980
And the key difference is this.

251
00:07:58,980 --> 00:08:00,860
Policies assigned at a management group

252
00:08:00,860 --> 00:08:03,660
cascade down to every subscription beneath it.

253
00:08:03,660 --> 00:08:04,660
Every single one.

254
00:08:04,660 --> 00:08:06,340
Roll assignments propagate.

255
00:08:06,340 --> 00:08:07,860
Baselines get inherited.

256
00:08:07,860 --> 00:08:10,380
You define something once at the management group level

257
00:08:10,380 --> 00:08:13,020
and it applies to hundreds of subscriptions automatically.

258
00:08:13,020 --> 00:08:14,780
That's where governance lives.

259
00:08:14,780 --> 00:08:16,620
When you write bicep at management groups scope,

260
00:08:16,620 --> 00:08:18,420
you're not deploying resources anymore.

261
00:08:18,420 --> 00:08:22,260
You're defining the rules that govern how resources can be deployed.

262
00:08:22,260 --> 00:08:24,580
You're saying every subscription under this management group

263
00:08:24,580 --> 00:08:27,820
must enforce TLS 1.2 for all storage accounts.

264
00:08:27,820 --> 00:08:31,340
You're saying every resource group must have these three tags.

265
00:08:31,340 --> 00:08:33,260
You're saying only these service principles

266
00:08:33,260 --> 00:08:35,300
can assign roles in these subscriptions.

267
00:08:35,300 --> 00:08:37,700
And here's where the architecture question becomes real.

268
00:08:37,700 --> 00:08:38,900
Are you building infrastructure?

269
00:08:38,900 --> 00:08:40,540
Or are you building the governance model

270
00:08:40,540 --> 00:08:42,220
that infrastructure happens to implement?

271
00:08:42,220 --> 00:08:43,700
Because those are different conversations,

272
00:08:43,700 --> 00:08:46,220
different skills, different approval processes,

273
00:08:46,220 --> 00:08:47,460
different stakeholders.

274
00:08:47,460 --> 00:08:50,980
The first decision point is biceps target scope parameter.

275
00:08:50,980 --> 00:08:54,180
That one line, target scope equal management group,

276
00:08:54,180 --> 00:08:56,460
determines whether you're thinking about serving one team's

277
00:08:56,460 --> 00:08:58,900
deployment needs or defining organizational control.

278
00:08:58,900 --> 00:09:00,060
It's not a technical detail.

279
00:09:00,060 --> 00:09:01,620
It's an architectural statement.

280
00:09:01,620 --> 00:09:03,300
Moving to management group scope

281
00:09:03,300 --> 00:09:05,220
doesn't just change what you can deploy.

282
00:09:05,220 --> 00:09:06,820
It changes how you think.

283
00:09:06,820 --> 00:09:08,580
You're suddenly managing inheritance.

284
00:09:08,580 --> 00:09:11,660
If you modify a policy at the platform management group level,

285
00:09:11,660 --> 00:09:14,460
what happens to the three child management groups beneath it?

286
00:09:14,460 --> 00:09:16,620
If you assign a role at the management group level,

287
00:09:16,620 --> 00:09:17,500
who inherits it?

288
00:09:17,500 --> 00:09:19,580
What happens when someone adds a new subscription?

289
00:09:19,580 --> 00:09:21,100
Does it automatically get the baseline

290
00:09:21,100 --> 00:09:22,780
or do you have to manually onboard it?

291
00:09:22,780 --> 00:09:24,380
Those aren't rhetorical questions.

292
00:09:24,380 --> 00:09:25,860
Those are the questions that determine

293
00:09:25,860 --> 00:09:28,500
whether your infrastructure survives organizational change

294
00:09:28,500 --> 00:09:29,700
or becomes a liability.

295
00:09:29,700 --> 00:09:31,380
This scope decision directly affects

296
00:09:31,380 --> 00:09:33,340
how you structure your modules.

297
00:09:33,340 --> 00:09:35,940
Parameters and variables, the contract layer.

298
00:09:35,940 --> 00:09:38,220
Parameters are your interface to the outside world.

299
00:09:38,220 --> 00:09:40,380
They are how someone using your template says what they want.

300
00:09:40,380 --> 00:09:41,780
But that's only half the story.

301
00:09:41,780 --> 00:09:43,940
In a hobby project, you might write a parameter

302
00:09:43,940 --> 00:09:45,620
like Param location string.

303
00:09:45,620 --> 00:09:47,060
Simple, open-ended.

304
00:09:47,060 --> 00:09:49,540
Whoever calls your template can put anything there.

305
00:09:49,540 --> 00:09:51,260
That flexibility feels good at first.

306
00:09:51,260 --> 00:09:52,580
You're not forcing constraints.

307
00:09:52,580 --> 00:09:54,500
You're trusting the user to know what they're doing.

308
00:09:54,500 --> 00:09:56,460
Enterprise bicep flips that assumption.

309
00:09:56,460 --> 00:09:58,300
You stop trusting flexibility.

310
00:09:58,300 --> 00:09:59,660
You start enforcing intent.

311
00:09:59,660 --> 00:10:02,740
A parameter in production bicep isn't just an input variable.

312
00:10:02,740 --> 00:10:03,580
It's a guardrail.

313
00:10:03,580 --> 00:10:06,340
It's the organizational rule embedded directly in the code.

314
00:10:06,340 --> 00:10:09,020
When you write Param location string in an enterprise template,

315
00:10:09,020 --> 00:10:10,500
you're not actually being flexible.

316
00:10:10,500 --> 00:10:11,420
You're being negligent.

317
00:10:11,420 --> 00:10:12,900
You're saying, we don't care if someone

318
00:10:12,900 --> 00:10:15,300
deploys to Kazakhstan because they mistyped the region name.

319
00:10:15,300 --> 00:10:16,380
We'll find out later.

320
00:10:16,380 --> 00:10:18,460
Instead, you use decorators at a loud,

321
00:10:18,460 --> 00:10:20,540
Easter's, Wester's, North Europe.

322
00:10:20,540 --> 00:10:22,020
Now the parameter is a contract.

323
00:10:22,020 --> 00:10:24,180
It says, these are the regions we support.

324
00:10:24,180 --> 00:10:27,140
Nothing else gets deployed, not because we're being restrictive.

325
00:10:27,140 --> 00:10:29,180
Because that's the actual organizational boundary.

326
00:10:29,180 --> 00:10:30,900
You've got data residency requirements.

327
00:10:30,900 --> 00:10:33,060
You've got network backbone in specific regions

328
00:10:33,060 --> 00:10:34,700
that you've got cost controls based on region.

329
00:10:34,700 --> 00:10:35,820
Those aren't technical details.

330
00:10:35,820 --> 00:10:37,060
Those are business rules.

331
00:10:37,060 --> 00:10:40,860
At min length three and at max length 24, aren't style guides.

332
00:10:40,860 --> 00:10:41,860
They're enforcement.

333
00:10:41,860 --> 00:10:43,980
A storage account name has hard limits in Azure.

334
00:10:43,980 --> 00:10:46,260
But your organization might have additional constraints.

335
00:10:46,260 --> 00:10:49,140
Maybe all storage account names must follow a specific pattern.

336
00:10:49,140 --> 00:10:51,540
Maybe they must start with your company prefix.

337
00:10:51,540 --> 00:10:54,380
The decorator layer is where that business logic lives.

338
00:10:54,380 --> 00:10:55,820
At descriptions looks cosmetic.

339
00:10:55,820 --> 00:10:56,500
It's not.

340
00:10:56,500 --> 00:10:58,660
It's documentation that surfaces in tooling

341
00:10:58,660 --> 00:11:00,980
in parameter files in IDE hints.

342
00:11:00,980 --> 00:11:02,540
When someone's writing a bicep file

343
00:11:02,540 --> 00:11:03,980
and they hover over your parameter,

344
00:11:03,980 --> 00:11:05,140
they don't just see the type.

345
00:11:05,140 --> 00:11:06,260
They see the meaning.

346
00:11:06,260 --> 00:11:07,660
This is the cost center that will be

347
00:11:07,660 --> 00:11:09,660
billed for this resource.

348
00:11:09,660 --> 00:11:10,620
That's context.

349
00:11:10,620 --> 00:11:12,180
That's what prevents mistakes.

350
00:11:12,180 --> 00:11:13,740
Variables do something different.

351
00:11:13,740 --> 00:11:15,220
They encode consistency.

352
00:11:15,220 --> 00:11:19,260
A parameter might say, "What are the tags for this resource?"

353
00:11:19,260 --> 00:11:21,500
A variable says, "If you didn't provide tags,

354
00:11:21,500 --> 00:11:22,460
here are the defaults."

355
00:11:22,460 --> 00:11:23,940
And here's the logic that applies

356
00:11:23,940 --> 00:11:26,980
organizational standards to whatever you did provide.

357
00:11:26,980 --> 00:11:30,180
A parameter might say, "What's the environment name?"

358
00:11:30,180 --> 00:11:32,780
A variable might apply that to determine the network range,

359
00:11:32,780 --> 00:11:35,580
the backup retention period, the monitoring verbosity.

360
00:11:35,580 --> 00:11:36,820
The parameter is the input.

361
00:11:36,820 --> 00:11:38,180
The variable is the business logic

362
00:11:38,180 --> 00:11:40,060
that translates that input into reality.

363
00:11:40,060 --> 00:11:41,220
The distinction matters.

364
00:11:41,220 --> 00:11:43,580
Hobby projects use parameters for flexibility.

365
00:11:43,580 --> 00:11:46,540
Enterprise projects use parameters to prevent mistakes

366
00:11:46,540 --> 00:11:48,940
and variables to enforce consistency.

367
00:11:48,940 --> 00:11:51,300
User-defined types let you push this further.

368
00:11:51,300 --> 00:11:52,740
You can create a type that represents

369
00:11:52,740 --> 00:11:54,620
a compliance storage account.

370
00:11:54,620 --> 00:11:56,260
That type encapsulates every decision

371
00:11:56,260 --> 00:11:58,260
about what makes a storage account compliant

372
00:11:58,260 --> 00:11:59,180
in your organization.

373
00:11:59,180 --> 00:12:00,980
Every time someone uses that type,

374
00:12:00,980 --> 00:12:02,620
they're inheriting all those decisions

375
00:12:02,620 --> 00:12:03,900
without having to reinvent them.

376
00:12:03,900 --> 00:12:06,220
Parameters and variables are where you move from

377
00:12:06,220 --> 00:12:08,420
the template that builds our infrastructure

378
00:12:08,420 --> 00:12:11,500
to the template that enforces our organizational standards.

379
00:12:11,500 --> 00:12:13,060
This enforcement is foundational

380
00:12:13,060 --> 00:12:16,540
because modules, the next layer up, are built on top of it.

381
00:12:16,540 --> 00:12:18,340
Modules as organizational standards.

382
00:12:18,340 --> 00:12:20,500
Now we get to the level where all of this comes together.

383
00:12:20,500 --> 00:12:23,180
Parameters and variables are the foundational layer.

384
00:12:23,180 --> 00:12:25,580
Scope decisions determine where governance lives,

385
00:12:25,580 --> 00:12:28,620
but modules are where the entire architectural vision

386
00:12:28,620 --> 00:12:31,180
crystallizes into something teams actually use.

387
00:12:31,180 --> 00:12:33,140
A module isn't just a reusable template.

388
00:12:33,140 --> 00:12:34,540
That's a technical description.

389
00:12:34,540 --> 00:12:35,620
A module is a contract.

390
00:12:35,620 --> 00:12:38,660
It says, this is how we do networking in our organization.

391
00:12:38,660 --> 00:12:40,060
This is how we do identity.

392
00:12:40,060 --> 00:12:41,820
This is how we do compliance.

393
00:12:41,820 --> 00:12:43,540
When someone consumes your module,

394
00:12:43,540 --> 00:12:45,900
they're not just getting a block of bicep code.

395
00:12:45,900 --> 00:12:47,940
They're inheriting organizational decision making.

396
00:12:47,940 --> 00:12:49,580
Here's the practical reality.

397
00:12:49,580 --> 00:12:52,620
As your verified modules, AVM provides the baseline.

398
00:12:52,620 --> 00:12:54,220
Microsoft has done the work to understand

399
00:12:54,220 --> 00:12:56,540
what a production-ready networking module looks like,

400
00:12:56,540 --> 00:12:58,220
what a compliance storage account needs,

401
00:12:58,220 --> 00:13:00,260
what a secure AKS cluster requires.

402
00:13:00,260 --> 00:13:01,620
You don't start from nothing.

403
00:13:01,620 --> 00:13:03,860
You inherit Microsoft's architectural thinking,

404
00:13:03,860 --> 00:13:05,540
but, and this is critical.

405
00:13:05,540 --> 00:13:08,700
Your organization's modules wrap AVM and add your rules.

406
00:13:08,700 --> 00:13:11,140
You don't just publish Microsoft's AVM module,

407
00:13:11,140 --> 00:13:12,980
you create an internal wrapper that wrapper

408
00:13:12,980 --> 00:13:14,700
might enforce your naming convention.

409
00:13:14,700 --> 00:13:16,620
It might require your cost-center tags.

410
00:13:16,620 --> 00:13:18,380
It might add your security baselines

411
00:13:18,380 --> 00:13:20,100
on top of Microsoft's defaults.

412
00:13:20,100 --> 00:13:22,860
It might constrain parameters to your approved SKUs.

413
00:13:22,860 --> 00:13:25,060
The wrapper becomes your organizational standard.

414
00:13:25,060 --> 00:13:26,780
Teams don't consume AVM directly.

415
00:13:26,780 --> 00:13:29,260
They consume your module, which happens to use AVM

416
00:13:29,260 --> 00:13:30,220
as its foundation.

417
00:13:30,220 --> 00:13:32,700
This is where the 70/30 split becomes visible.

418
00:13:32,700 --> 00:13:34,980
70% of what a module does is strategic.

419
00:13:34,980 --> 00:13:36,620
It encodes business decisions.

420
00:13:36,620 --> 00:13:38,420
What naming pattern do we use?

421
00:13:38,420 --> 00:13:40,100
What security controls matter to us?

422
00:13:40,100 --> 00:13:41,300
What monitoring is mandatory?

423
00:13:41,300 --> 00:13:43,060
What cost controls apply?

424
00:13:43,060 --> 00:13:44,380
30% is technical.

425
00:13:44,380 --> 00:13:47,100
The actual biceps syntax that implements those decisions.

426
00:13:47,100 --> 00:13:48,380
When you design a module,

427
00:13:48,380 --> 00:13:50,020
you're not sitting in a technical meeting

428
00:13:50,020 --> 00:13:51,660
deciding how ARM templates work.

429
00:13:51,660 --> 00:13:53,620
You're sitting in an architecture meeting,

430
00:13:53,620 --> 00:13:55,500
deciding how your organization works.

431
00:13:55,500 --> 00:13:57,740
There are three types of modules in the mature model.

432
00:13:57,740 --> 00:13:59,420
Understanding the distinction changes

433
00:13:59,420 --> 00:14:02,060
how you organize your entire module strategy.

434
00:14:02,060 --> 00:14:04,780
Resource modules wrap a single as your resource.

435
00:14:04,780 --> 00:14:07,380
A storage account, a virtual network, a key vault,

436
00:14:07,380 --> 00:14:09,300
but they wrap it with organizational guardrails

437
00:14:09,300 --> 00:14:10,380
already baked in.

438
00:14:10,380 --> 00:14:11,740
You can't create a storage account

439
00:14:11,740 --> 00:14:13,860
through the module without encryption enabled.

440
00:14:13,860 --> 00:14:15,020
You can't deploy a network

441
00:14:15,020 --> 00:14:17,700
without the required network security groups configured.

442
00:14:17,700 --> 00:14:19,540
The module takes complexity of the table.

443
00:14:19,540 --> 00:14:21,660
Pattern modules orchestrate multiple resources

444
00:14:21,660 --> 00:14:24,980
into a recognized architecture, a hub spoke network pattern,

445
00:14:24,980 --> 00:14:26,820
a landing zone for a workload,

446
00:14:26,820 --> 00:14:29,460
a secure AKS cluster with all its prerequisites.

447
00:14:29,460 --> 00:14:31,380
These modules are where architectural decisions

448
00:14:31,380 --> 00:14:32,540
become reusable.

449
00:14:32,540 --> 00:14:34,860
You're not just standardizing individual resources,

450
00:14:34,860 --> 00:14:37,380
you're standardizing how those resources fit together.

451
00:14:37,380 --> 00:14:39,100
Platform modules are the broadest layer,

452
00:14:39,100 --> 00:14:40,380
these are the entire subscriptions

453
00:14:40,380 --> 00:14:41,940
as a service blueprints.

454
00:14:41,940 --> 00:14:43,180
Everything needed to hand a team

455
00:14:43,180 --> 00:14:46,060
a fully configured environment, networking, identity

456
00:14:46,060 --> 00:14:48,860
integration, baseline policies, monitoring stacks,

457
00:14:48,860 --> 00:14:51,780
security controls, all is one coherent unit.

458
00:14:51,780 --> 00:14:53,300
The architectural hierarchy matters

459
00:14:53,300 --> 00:14:55,860
because it mirrors how your organization actually works.

460
00:14:55,860 --> 00:14:57,780
A platform team defines platform modules,

461
00:14:57,780 --> 00:14:59,740
teams build pattern modules on top of them,

462
00:14:59,740 --> 00:15:01,540
application teams use resource modules

463
00:15:01,540 --> 00:15:02,780
to fill in specifics.

464
00:15:02,780 --> 00:15:04,980
Different governance applies at each layer.

465
00:15:04,980 --> 00:15:06,460
Versioning becomes critical here,

466
00:15:06,460 --> 00:15:07,820
and this isn't theoretical.

467
00:15:07,820 --> 00:15:09,460
A resource module has a breaking change.

468
00:15:09,460 --> 00:15:11,340
Maybe you remove the deprecated parameter,

469
00:15:11,340 --> 00:15:13,020
maybe you change the output structure

470
00:15:13,020 --> 00:15:15,060
if 30 teams depend on that module

471
00:15:15,060 --> 00:15:16,900
and you deploy that breaking change,

472
00:15:16,900 --> 00:15:19,260
30 teams suddenly have broken templates.

473
00:15:19,260 --> 00:15:21,660
This isn't a compilation error they catch at test time,

474
00:15:21,660 --> 00:15:22,860
this is production breakage.

475
00:15:22,860 --> 00:15:24,940
This is why module versioning isn't optional.

476
00:15:24,940 --> 00:15:27,500
It's a hard requirement, semantic versioning,

477
00:15:27,500 --> 00:15:30,300
clear deprecation parts, migration guides.

478
00:15:30,300 --> 00:15:33,300
The governance question becomes operational.

479
00:15:33,300 --> 00:15:34,740
Who can publish modules?

480
00:15:34,740 --> 00:15:36,940
In some organizations, anyone can.

481
00:15:36,940 --> 00:15:39,700
In most mature ones, no, the platform team publishes.

482
00:15:39,700 --> 00:15:42,780
Application teams request new modules or modifications,

483
00:15:42,780 --> 00:15:44,500
reviews happen, testing happens.

484
00:15:44,500 --> 00:15:46,260
Once it's released, it's stable.

485
00:15:46,260 --> 00:15:48,460
It won't break without explicit version bumping.

486
00:15:48,460 --> 00:15:51,380
Who reviews them before publication, usually cross-functional?

487
00:15:51,380 --> 00:15:52,940
Does it meet security standards?

488
00:15:52,940 --> 00:15:54,340
Does it follow naming conventions?

489
00:15:54,340 --> 00:15:56,300
Does it align with organizational cost controls?

490
00:15:56,300 --> 00:15:58,300
Does it integrate with the monitoring baseline?

491
00:15:58,300 --> 00:15:59,380
How do you enforce their use?

492
00:15:59,380 --> 00:16:00,460
That's where policy comes in.

493
00:16:00,460 --> 00:16:02,460
You might prevent teams from deploying certain resources

494
00:16:02,460 --> 00:16:04,220
directly, they must use the module.

495
00:16:04,220 --> 00:16:06,020
You might audit, which modules are being used

496
00:16:06,020 --> 00:16:07,300
across the organization.

497
00:16:07,300 --> 00:16:08,740
You might deprecate old modules

498
00:16:08,740 --> 00:16:10,620
by refusing to renew their support.

499
00:16:10,620 --> 00:16:13,300
Modules become the unit of organizational control.

500
00:16:13,300 --> 00:16:14,940
This multiplies the architecture problem

501
00:16:14,940 --> 00:16:17,260
across every team and every deployment.

502
00:16:17,260 --> 00:16:20,260
Outputs and dependencies, the invisible architecture.

503
00:16:20,260 --> 00:16:22,220
Outputs might be the most underestimated part

504
00:16:22,220 --> 00:16:23,620
of bicep architecture.

505
00:16:23,620 --> 00:16:25,460
When you're writing a module, outputs

506
00:16:25,460 --> 00:16:28,180
feel like afterthought work, you extract the resource idea

507
00:16:28,180 --> 00:16:29,100
of what you just created.

508
00:16:29,100 --> 00:16:31,100
You throw it in an output block, done.

509
00:16:31,100 --> 00:16:33,740
That's not architecture, that's plumbing.

510
00:16:33,740 --> 00:16:35,780
In reality, outputs define the interface

511
00:16:35,780 --> 00:16:37,700
between layers of your infrastructure.

512
00:16:37,700 --> 00:16:39,220
They're not values you extract.

513
00:16:39,220 --> 00:16:42,460
Their promise is about what downstream systems can rely on.

514
00:16:42,460 --> 00:16:44,420
Picture this, you've got a networking module.

515
00:16:44,420 --> 00:16:46,980
It creates a virtual network, subnet's network security

516
00:16:46,980 --> 00:16:48,300
groups, root tables.

517
00:16:48,300 --> 00:16:50,180
At the end, it outputs the subnet ID.

518
00:16:50,180 --> 00:16:52,860
That subnet ID gets consumed by an application module.

519
00:16:52,860 --> 00:16:55,900
That application module deploys VMs into that subnet.

520
00:16:55,900 --> 00:16:58,380
The dependency relationship between those two modules,

521
00:16:58,380 --> 00:17:00,580
the fact that one produces what the other consumes,

522
00:17:00,580 --> 00:17:01,620
that's your architecture.

523
00:17:01,620 --> 00:17:03,340
It's not written down in a diagram.

524
00:17:03,340 --> 00:17:06,100
It lives in the outputs and the parameters that consume them.

525
00:17:06,100 --> 00:17:07,660
Now, scale that across an enterprise.

526
00:17:07,660 --> 00:17:10,220
You've got dozens of modules, hundreds of deployments.

527
00:17:10,220 --> 00:17:12,740
The networking team publishes a new version of their module.

528
00:17:12,740 --> 00:17:14,420
They optimize the subnet ID format,

529
00:17:14,420 --> 00:17:15,940
or they change how subnets are named,

530
00:17:15,940 --> 00:17:18,340
or they add a new output that more accurately

531
00:17:18,340 --> 00:17:20,060
represents what's actually available.

532
00:17:20,060 --> 00:17:22,620
That change cascades through every application module

533
00:17:22,620 --> 00:17:23,980
that depends on that output.

534
00:17:23,980 --> 00:17:25,980
It cascades through every team's pipeline.

535
00:17:25,980 --> 00:17:27,420
It cascades through every deployment.

536
00:17:27,420 --> 00:17:30,060
This is where enterprise bicep runs into complexity

537
00:17:30,060 --> 00:17:31,820
that hobby projects never see.

538
00:17:31,820 --> 00:17:34,860
In a small environment, you've got maybe five modules in total.

539
00:17:34,860 --> 00:17:36,780
You can track the dependencies in your head.

540
00:17:36,780 --> 00:17:38,740
In a large organization, you've got hundreds.

541
00:17:38,740 --> 00:17:40,700
The dependency graph becomes invisible.

542
00:17:40,700 --> 00:17:43,260
A change in one place breaks things in 10 others.

543
00:17:43,260 --> 00:17:44,860
Teams don't even know the connection exists

544
00:17:44,860 --> 00:17:46,540
until production starts failing.

545
00:17:46,540 --> 00:17:48,340
Here's the architectural problem.

546
00:17:48,340 --> 00:17:50,700
Bicep doesn't have a built-in dependency resolver.

547
00:17:50,700 --> 00:17:53,340
There's no system that says if this output changes,

548
00:17:53,340 --> 00:17:54,860
warn all consumers.

549
00:17:54,860 --> 00:17:57,900
You have to manage it manually through parameter files,

550
00:17:57,900 --> 00:17:59,180
through orchestration logic,

551
00:17:59,180 --> 00:18:01,460
through careful naming conventions and documentation,

552
00:18:01,460 --> 00:18:02,860
through discipline.

553
00:18:02,860 --> 00:18:05,620
This is why outputs need to be minimal and intentional.

554
00:18:05,620 --> 00:18:09,300
Every output you expose is a surface that others will build on.

555
00:18:09,300 --> 00:18:10,580
Every output is a contract.

556
00:18:10,580 --> 00:18:12,700
When you add an output, you're making a promise.

557
00:18:12,700 --> 00:18:14,540
Downstream modules can rely on this.

558
00:18:14,540 --> 00:18:16,180
If you remove it, you break that promise.

559
00:18:16,180 --> 00:18:18,220
If you change its format, you break that promise.

560
00:18:18,220 --> 00:18:19,860
The smaller your output surface,

561
00:18:19,860 --> 00:18:21,420
the fewer promises you make.

562
00:18:21,420 --> 00:18:23,380
The fewer promises, the more flexibility

563
00:18:23,380 --> 00:18:26,180
you have to change your module without cascading failures.

564
00:18:26,180 --> 00:18:28,020
The architectural question becomes this,

565
00:18:28,020 --> 00:18:30,140
are your outputs enabling flexibility?

566
00:18:30,140 --> 00:18:31,900
Or are they creating hidden coupling?

567
00:18:31,900 --> 00:18:35,340
A poorly designed output exposes internal implementation details.

568
00:18:35,340 --> 00:18:36,860
Here's the exact resource ID,

569
00:18:36,860 --> 00:18:39,380
formatted like this, named exactly this way.

570
00:18:39,380 --> 00:18:42,340
Now, downstream modules are coupled to those specifics.

571
00:18:42,340 --> 00:18:44,180
If you change the naming, everything breaks.

572
00:18:44,180 --> 00:18:46,580
If you refactor internally, everything breaks.

573
00:18:46,580 --> 00:18:49,580
A well-designed output provides a semantic contract.

574
00:18:49,580 --> 00:18:51,700
Here's what you need to access the network capability

575
00:18:51,700 --> 00:18:53,060
this module provides.

576
00:18:53,060 --> 00:18:54,620
The implementation might change.

577
00:18:54,620 --> 00:18:55,860
The output stays stable.

578
00:18:55,860 --> 00:18:57,420
That's the difference between outputs

579
00:18:57,420 --> 00:18:59,220
that enable architecture and outputs

580
00:18:59,220 --> 00:19:01,140
that create scaffolding you're locked into.

581
00:19:01,140 --> 00:19:02,820
Managing these dependencies at scale

582
00:19:02,820 --> 00:19:04,500
requires a completely different approach

583
00:19:04,500 --> 00:19:06,260
to how you orchestrate deployments.

584
00:19:06,260 --> 00:19:08,980
Deployment stacks, the state management breakthrough.

585
00:19:08,980 --> 00:19:12,220
For years, bicep had a structural gap that Terraform didn't.

586
00:19:12,220 --> 00:19:14,660
You could deploy resources, as your would create them.

587
00:19:14,660 --> 00:19:16,100
And then, the relationship ended.

588
00:19:16,100 --> 00:19:18,940
You'd run a bicep template, resources appeared in Azure.

589
00:19:18,940 --> 00:19:21,020
Weeks later, you'd modify the template,

590
00:19:21,020 --> 00:19:23,660
remove a resource, redeploy, and as you wouldn't know,

591
00:19:23,660 --> 00:19:26,740
it wouldn't track which resources belonged to that deployment.

592
00:19:26,740 --> 00:19:29,540
It wouldn't know if the removed resource should disappear

593
00:19:29,540 --> 00:19:31,780
or stick around, you'd have to manage that yourself,

594
00:19:31,780 --> 00:19:33,860
delete it manually, or leave it often,

595
00:19:33,860 --> 00:19:35,700
or write scripts that try to guess.

596
00:19:35,700 --> 00:19:37,820
This is why brownfield environments get messy.

597
00:19:37,820 --> 00:19:40,180
Years of deployments stack on top of each other.

598
00:19:40,180 --> 00:19:42,540
Nobody knows which resources are safe to delete

599
00:19:42,540 --> 00:19:44,580
and which are supporting some critical workflow

600
00:19:44,580 --> 00:19:45,980
that nobody documents.

601
00:19:45,980 --> 00:19:47,980
Terraform solved this with state.

602
00:19:47,980 --> 00:19:49,660
A-Pont-TF state file that said,

603
00:19:49,660 --> 00:19:50,940
"I created these resources.

604
00:19:50,940 --> 00:19:52,140
These are my responsibility.

605
00:19:52,140 --> 00:19:53,780
If they're no longer in my configuration,

606
00:19:53,780 --> 00:19:55,380
they should be cleaned up."

607
00:19:55,380 --> 00:19:57,100
State made infrastructure predictable,

608
00:19:57,100 --> 00:19:58,860
but state came with operational cost.

609
00:19:58,860 --> 00:20:02,420
You had to store it securely, lock it during updates, back it up,

610
00:20:02,420 --> 00:20:06,100
manage its life cycle, like production data, because it was.

611
00:20:06,100 --> 00:20:08,860
Deployment stacks bring Terraforms model into Azure natively,

612
00:20:08,860 --> 00:20:11,900
no separate state file, no external storage complexity,

613
00:20:11,900 --> 00:20:15,140
but the same fundamental capability, ownership tracking.

614
00:20:15,140 --> 00:20:17,420
A deployment stack is an Azure resource,

615
00:20:17,420 --> 00:20:20,620
not a file, not a concept, an actual resource of type Microsoft.

616
00:20:20,620 --> 00:20:23,060
Resources deployment stacks that sits in Azure

617
00:20:23,060 --> 00:20:25,060
and owns a collection of other resources.

618
00:20:25,060 --> 00:20:27,260
When you create a stack, it wraps your bicep template.

619
00:20:27,260 --> 00:20:30,340
Every time you deploy, the stack maintains a manifest of what it owns.

620
00:20:30,340 --> 00:20:32,220
New resources get added to the manifest,

621
00:20:32,220 --> 00:20:33,900
change resources get updated,

622
00:20:33,900 --> 00:20:36,580
removed resources get handled according to your settings,

623
00:20:36,580 --> 00:20:39,220
and here's where the life cycle options become critical.

624
00:20:39,220 --> 00:20:41,140
Delete resources is the aggressive option.

625
00:20:41,140 --> 00:20:43,220
You remove a resource from your bicep template,

626
00:20:43,220 --> 00:20:46,020
redeploy the stack, and Azure deletes that resource.

627
00:20:46,020 --> 00:20:49,460
Completely, automatically, this is powerful for dev and test environments.

628
00:20:49,460 --> 00:20:50,980
Spin up a Dev stack in the morning,

629
00:20:50,980 --> 00:20:54,180
deleted at night, everything disappears, no often resources,

630
00:20:54,180 --> 00:20:56,260
no stray databases, still accruing charges,

631
00:20:56,260 --> 00:20:57,820
because nobody remembered to clean them up.

632
00:20:57,820 --> 00:21:00,620
But delete resources in production is a different conversation.

633
00:21:00,620 --> 00:21:04,220
You remove a resource by accident, code gets merged, pipeline runs,

634
00:21:04,220 --> 00:21:07,380
your database is gone, that's not governance, that's catastrophe.

635
00:21:07,380 --> 00:21:09,900
So the safer production approach is detachable,

636
00:21:09,900 --> 00:21:13,140
you remove the resource from the template, the stack stops managing it,

637
00:21:13,140 --> 00:21:14,740
but the resource stays in Azure.

638
00:21:14,740 --> 00:21:17,620
You can delete it manually or migrate it to another stack or

639
00:21:17,620 --> 00:21:19,540
hand it off to someone else who owns it.

640
00:21:19,540 --> 00:21:21,460
The stack is saying, I no longer own this,

641
00:21:21,460 --> 00:21:23,620
what happens to it is someone else's decision.

642
00:21:23,620 --> 00:21:25,860
There's also detach resources, which is surgical.

643
00:21:25,860 --> 00:21:28,660
You specify exactly which resources get detached.

644
00:21:28,660 --> 00:21:30,780
Everything else follows the delete behavior.

645
00:21:30,780 --> 00:21:34,060
This matters for complex migrations where you're gradually moving resources

646
00:21:34,060 --> 00:21:35,340
under stack management.

647
00:21:35,340 --> 00:21:38,180
Some resources stay with the stack, others get handed off.

648
00:21:38,180 --> 00:21:41,620
Deny settings are the governance layer on top of life cycle management.

649
00:21:41,620 --> 00:21:43,820
By default, once the stack owns a resource,

650
00:21:43,820 --> 00:21:48,020
anyone with contributor access can still manually modify that resource in the portal.

651
00:21:48,020 --> 00:21:49,940
That breaks the code is truth principle.

652
00:21:49,940 --> 00:21:53,180
Deny settings fixes when you enable deny, write and delete on a stack

653
00:21:53,180 --> 00:21:57,540
Azure prevents modifications to stack own resources outside the ISE workflow.

654
00:21:57,540 --> 00:21:58,820
The portal buttons don't work.

655
00:21:58,820 --> 00:22:01,740
CLI commands are blocked even if you have the permissions.

656
00:22:01,740 --> 00:22:03,460
You can't change those resources.

657
00:22:03,460 --> 00:22:06,020
The only way to modify them is through the stack,

658
00:22:06,020 --> 00:22:08,140
which means through the bicep template,

659
00:22:08,140 --> 00:22:10,420
through the pipeline, through code review and approval.

660
00:22:10,420 --> 00:22:12,340
This is where discipline becomes architectural.

661
00:22:12,340 --> 00:22:14,420
You're not trusting teams to follow a process.

662
00:22:14,420 --> 00:22:15,980
The system enforces the process.

663
00:22:15,980 --> 00:22:18,460
Configuration drift becomes technically impossible,

664
00:22:18,460 --> 00:22:19,700
not just discouraged.

665
00:22:19,700 --> 00:22:23,100
Stacks work at resource group, subscription and management group scopes.

666
00:22:23,100 --> 00:22:24,260
This is significant.

667
00:22:24,260 --> 00:22:28,060
A stack at subscription scope can own resources across multiple resource groups.

668
00:22:28,060 --> 00:22:31,060
You're not confined to single resource group deployments anymore.

669
00:22:31,060 --> 00:22:33,660
You can deploy an entire subscription as a coherent unit.

670
00:22:33,660 --> 00:22:37,660
Every resource, every policy, every role assignment, managed by one stack.

671
00:22:37,660 --> 00:22:38,700
Update the stack template.

672
00:22:38,700 --> 00:22:40,900
The entire subscription converges to the new state.

673
00:22:40,900 --> 00:22:43,540
This changes environment management fundamentally.

674
00:22:43,540 --> 00:22:45,380
Development environments become temporary.

675
00:22:45,380 --> 00:22:48,380
Provisioned on demand, deleted completely at the end of the day.

676
00:22:48,380 --> 00:22:50,220
Production environments become versioned.

677
00:22:50,220 --> 00:22:51,820
The stack template lives in Git.

678
00:22:51,820 --> 00:22:55,900
Every changes traced, rollback is just deploying an older template version.

679
00:22:55,900 --> 00:22:57,020
The implication is this.

680
00:22:57,020 --> 00:23:00,660
You can finally implement true environment lifecycle management in Azure natively.

681
00:23:00,660 --> 00:23:06,300
Spin up, update, tear down, all predictably, all auditable, all under code control.

682
00:23:06,300 --> 00:23:08,700
This is the foundation for governance at scale.

683
00:23:08,700 --> 00:23:11,660
Management group scope, governance at the tenant level.

684
00:23:11,660 --> 00:23:13,500
You've moved past resource group thinking.

685
00:23:13,500 --> 00:23:15,900
You've accepted that scope matters architecturally.

686
00:23:15,900 --> 00:23:19,260
Now you're standing at the level where organizational governance actually lives.

687
00:23:19,260 --> 00:23:22,220
Management groups sit above subscriptions in the Azure hierarchy.

688
00:23:22,220 --> 00:23:26,900
They are the tier most teams never interact with directly unless they're in a platform or governance role.

689
00:23:26,900 --> 00:23:28,500
But that invisibility is the point.

690
00:23:28,500 --> 00:23:32,180
Management groups are where policy cascades, where role assignments propagate,

691
00:23:32,180 --> 00:23:36,660
where a single decision made at the right level applies to hundreds of subscriptions automatically.

692
00:23:36,660 --> 00:23:39,780
When you deploy bicep with target scope, e-polls management group,

693
00:23:39,780 --> 00:23:41,420
you're no longer defining resources.

694
00:23:41,420 --> 00:23:45,300
You're defining the rules that govern how resources can exist in your organization.

695
00:23:45,300 --> 00:23:47,060
Think about what that means operationally.

696
00:23:47,060 --> 00:23:48,580
You write a policy definition.

697
00:23:48,580 --> 00:23:50,740
You assign it at a management group scope.

698
00:23:50,740 --> 00:23:55,820
Every subscription beneath that group, whether there are 10 or 200, inherits that policy.

699
00:23:55,820 --> 00:24:00,580
Every resource created in every one of those subscriptions gets evaluated against that policy.

700
00:24:00,580 --> 00:24:02,740
You didn't deploy that policy to 200 subscriptions.

701
00:24:02,740 --> 00:24:05,100
You deployed it once, the hierarchy did the work.

702
00:24:05,100 --> 00:24:07,740
The typical organizational structure looks like this.

703
00:24:07,740 --> 00:24:10,180
Tenant route sits at the very top.

704
00:24:10,180 --> 00:24:12,380
Beneath it, you've got a platform management group.

705
00:24:12,380 --> 00:24:15,580
This is where central infrastructure lives, where shared services,

706
00:24:15,580 --> 00:24:18,620
connectivity standards and security baselines are defined.

707
00:24:18,620 --> 00:24:20,780
Beneath platform, you've got landing zones.

708
00:24:20,780 --> 00:24:23,260
This is the actual structure where application teams sit.

709
00:24:23,260 --> 00:24:26,460
And beneath landing zones, you've got individual subscriptions,

710
00:24:26,460 --> 00:24:29,340
production subscriptions, non-production subscriptions,

711
00:24:29,340 --> 00:24:33,420
sandbox subscriptions, each one inheriting governance from the level above.

712
00:24:33,420 --> 00:24:37,260
What you're deploying at management group scope are primarily three resource types.

713
00:24:37,260 --> 00:24:42,060
Policy definitions, the actual rules, policy initiatives, bundles of multiple policies

714
00:24:42,060 --> 00:24:45,660
that work together as a coherent governance model, and our back assignments,

715
00:24:45,660 --> 00:24:48,300
role assignments that determine who can do what at what scope.

716
00:24:48,300 --> 00:24:52,740
You're also deploying things like diagnostic settings that push logs to centralize monitoring

717
00:24:52,740 --> 00:24:55,660
and custom role definitions that your organization needs.

718
00:24:55,660 --> 00:24:59,020
The architectural shift here is that governance is no longer something you do

719
00:24:59,020 --> 00:25:00,300
after infrastructure is built.

720
00:25:00,300 --> 00:25:03,420
It's not a separate process, it's part of the infrastructure definition.

721
00:25:03,420 --> 00:25:07,740
You're not building a resource group, then separately deciding what policies apply to it.

722
00:25:07,740 --> 00:25:10,780
You're defining a management group with specific policies already embedded.

723
00:25:10,780 --> 00:25:14,460
That management group becomes a container that enforces governance

724
00:25:14,460 --> 00:25:16,380
on everything created within it.

725
00:25:16,380 --> 00:25:18,140
This requires elevated permissions.

726
00:25:18,140 --> 00:25:21,580
You can't deploy to management group scope from a standard developer account.

727
00:25:21,580 --> 00:25:23,820
This is intentional, it's a forcing function.

728
00:25:23,820 --> 00:25:27,180
Governance changes aren't something casual, they're deliberate, they're auditable,

729
00:25:27,180 --> 00:25:28,860
they go through approval processes,

730
00:25:28,860 --> 00:25:33,340
someone signs off on the fact that we're changing how the entire organization's cloud infrastructure behaves.

731
00:25:33,340 --> 00:25:34,700
Here's where this becomes real.

732
00:25:34,700 --> 00:25:38,300
When a new subscription gets created and placed under a management group you've configured,

733
00:25:38,300 --> 00:25:42,060
it doesn't need individual setup, it doesn't need a team to manually apply policies.

734
00:25:42,060 --> 00:25:43,100
It inherits everything.

735
00:25:43,100 --> 00:25:46,540
The policies, the role assignments, the monitoring baselines, the compliance checks,

736
00:25:46,540 --> 00:25:47,900
the governance is already there.

737
00:25:47,900 --> 00:25:50,060
The subscription is already compliant by definition.

738
00:25:50,060 --> 00:25:53,580
That's not a deployment convenience, that's a change in how you think about onboarding.

739
00:25:53,580 --> 00:25:55,340
It also changes what maintenance means.

740
00:25:55,340 --> 00:25:59,260
If the security team decides that all storage accounts need a new encryption requirement,

741
00:25:59,260 --> 00:26:01,420
they don't update hundreds of policies individually,

742
00:26:01,420 --> 00:26:03,420
they update the policy definition once.

743
00:26:03,420 --> 00:26:06,060
The change propagates down, every subscription sees it,

744
00:26:06,060 --> 00:26:09,660
every resource gets re-evaluated, compliance reports update automatically,

745
00:26:09,660 --> 00:26:11,660
one change, organizational scale,

746
00:26:11,660 --> 00:26:14,860
but this only works if governance is truly codified, if it lives in bicep.

747
00:26:14,860 --> 00:26:19,420
If it's versioned in Git, if it goes through the same review and approval process as application code.

748
00:26:19,420 --> 00:26:22,860
If it's not, your back-to-manual process is at organizational scale.

749
00:26:22,860 --> 00:26:25,100
That's the opposite of what you are trying to achieve.

750
00:26:25,100 --> 00:26:28,300
This is why management group scope isn't optional for enterprise bicep.

751
00:26:28,300 --> 00:26:29,500
It's foundational.

752
00:26:29,500 --> 00:26:32,140
Azure Policy has code enforcement through bicep.

753
00:26:32,140 --> 00:26:33,580
Now you have the structure.

754
00:26:33,580 --> 00:26:36,060
Management group hierarchies, scopes defined,

755
00:26:36,060 --> 00:26:38,220
the governance model sitting at the tenant level,

756
00:26:38,220 --> 00:26:41,020
but structure is just the skeleton, the actual enforcement,

757
00:26:41,020 --> 00:26:44,140
the part that stops bad things from happening, that's Azure Policy.

758
00:26:44,140 --> 00:26:45,980
Azure Policy is the mechanism.

759
00:26:45,980 --> 00:26:47,340
Bicep is how you define it.

760
00:26:47,340 --> 00:26:48,780
This is a crucial distinction.

761
00:26:48,780 --> 00:26:51,420
You can write policies in the portal, click through a UI,

762
00:26:51,420 --> 00:26:54,220
build rules visually, many organizations do exactly that,

763
00:26:54,220 --> 00:26:55,420
but that's not architecture.

764
00:26:55,420 --> 00:26:58,780
That's configuration that nobody can review, track or reproduce.

765
00:26:58,780 --> 00:27:00,700
Enterprise governance lives in code.

766
00:27:00,700 --> 00:27:02,860
Policy definitions are the fundamental unit.

767
00:27:02,860 --> 00:27:04,220
They are the actual rules.

768
00:27:04,220 --> 00:27:06,060
A policy definition might say,

769
00:27:06,060 --> 00:27:08,620
all storage accounts must have encryption enabled.

770
00:27:08,620 --> 00:27:09,580
Another might say,

771
00:27:09,580 --> 00:27:12,940
only these three Azure regions are allowed for resource deployment.

772
00:27:12,940 --> 00:27:16,220
Another, every resource must have a cost center tag.

773
00:27:16,220 --> 00:27:17,020
These are constraints.

774
00:27:17,020 --> 00:27:18,460
They're written as JSON rules,

775
00:27:18,460 --> 00:27:20,700
and they can be deployed via bicep as Microsoft.

776
00:27:21,580 --> 00:27:24,860
Authorization swash policy definitions resources.

777
00:27:24,860 --> 00:27:27,020
You've got two sources for these definitions.

778
00:27:27,020 --> 00:27:29,740
Custom definitions rules your organization rights

779
00:27:29,740 --> 00:27:31,340
because they matter to your business,

780
00:27:31,340 --> 00:27:32,700
and built-in definitions.

781
00:27:32,700 --> 00:27:36,140
Microsoft's rules for security, compliance, and best practice.

782
00:27:36,140 --> 00:27:38,780
Both deploy the same way, both get assigned the same way,

783
00:27:38,780 --> 00:27:40,300
but the distinction matters,

784
00:27:40,300 --> 00:27:42,380
built-in policies get updated by Microsoft.

785
00:27:42,380 --> 00:27:44,780
Custom policies are your responsibility to maintain.

786
00:27:44,780 --> 00:27:46,220
The next layer is initiatives.

787
00:27:46,220 --> 00:27:49,420
An initiative also called a policy set definition

788
00:27:49,420 --> 00:27:51,340
bundles multiple policies together

789
00:27:51,340 --> 00:27:53,180
into a coherent governance model.

790
00:27:53,180 --> 00:27:55,420
A security baseline initiative might include

791
00:27:55,420 --> 00:27:58,300
20 individual policies, encryption requirements,

792
00:27:58,300 --> 00:28:01,900
authentication standards, logging rules, access controls,

793
00:28:01,900 --> 00:28:03,660
all the pieces that together define

794
00:28:03,660 --> 00:28:06,060
what security looks like in your organization.

795
00:28:06,060 --> 00:28:08,220
Instead of assigning policies individually,

796
00:28:08,220 --> 00:28:10,540
you assign the initiative one action.

797
00:28:10,540 --> 00:28:11,820
20 policies applied.

798
00:28:11,820 --> 00:28:14,620
Assignments are where the work actually happens.

799
00:28:14,620 --> 00:28:16,300
A policy definition is a rule,

800
00:28:16,300 --> 00:28:18,380
an assignment is that rule applied to a scope.

801
00:28:18,380 --> 00:28:20,140
You might assign a baseline initiative

802
00:28:20,140 --> 00:28:21,820
at your platform management group.

803
00:28:21,820 --> 00:28:24,700
Now every subscription beneath that group inherits the policy.

804
00:28:24,700 --> 00:28:26,460
Every resource created gets evaluated,

805
00:28:26,460 --> 00:28:27,820
compliant or non-compliant.

806
00:28:27,820 --> 00:28:30,060
That evaluation doesn't require manual review.

807
00:28:30,060 --> 00:28:32,620
It's automatic, continuous, built into the platform.

808
00:28:32,620 --> 00:28:34,540
Now here's where the architecture gets interesting.

809
00:28:34,540 --> 00:28:36,700
Policy has an effect called deploy if not exists.

810
00:28:36,700 --> 00:28:38,060
This isn't just evaluation.

811
00:28:38,060 --> 00:28:39,660
This is enforcement by deployment.

812
00:28:39,660 --> 00:28:42,460
The policy doesn't just check if your storage account has encryption.

813
00:28:42,460 --> 00:28:44,700
It can actually deploy an encryption configuration

814
00:28:44,700 --> 00:28:45,340
if it's missing.

815
00:28:45,340 --> 00:28:46,060
That's powerful.

816
00:28:46,060 --> 00:28:48,380
It's also constrained in ways that matter architecturally.

817
00:28:48,380 --> 00:28:49,580
The constraint is scope.

818
00:28:49,580 --> 00:28:52,540
Deploy if not exists works at subscription scope.

819
00:28:52,540 --> 00:28:53,500
At resource group scope.

820
00:28:53,500 --> 00:28:54,780
But not at management group scope.

821
00:28:54,780 --> 00:28:56,620
You can't write a policy that automatically

822
00:28:56,620 --> 00:28:58,780
deploys something to the management group itself.

823
00:28:58,780 --> 00:29:00,060
This is a technical limitation

824
00:29:00,060 --> 00:29:03,180
that shapes how you distribute governance across your infrastructure.

825
00:29:03,180 --> 00:29:04,540
This limitation drives a pattern

826
00:29:04,540 --> 00:29:06,620
that separates concerns cleanly.

827
00:29:06,620 --> 00:29:08,620
Use bicep deployments at management group scope

828
00:29:08,620 --> 00:29:10,860
for the governance artifacts themselves.

829
00:29:10,860 --> 00:29:13,740
Policy definitions, initiatives, role assignments.

830
00:29:13,740 --> 00:29:15,740
These are the rules and the access controls.

831
00:29:15,740 --> 00:29:18,460
Then use policy assignments also deployed via bicep

832
00:29:18,460 --> 00:29:19,660
to apply those rules.

833
00:29:19,660 --> 00:29:22,620
For anything that needs to deploy to a subscription or resource group,

834
00:29:22,620 --> 00:29:25,340
maybe a compliance module, maybe a monitoring agent,

835
00:29:25,340 --> 00:29:27,980
use deploy if not exists policies.

836
00:29:27,980 --> 00:29:31,500
Let the policy engine handle the deployment to the subscription level.

837
00:29:31,500 --> 00:29:33,180
The result is clean separation.

838
00:29:33,180 --> 00:29:34,940
Bicep handles the structural governance

839
00:29:34,940 --> 00:29:36,540
at the management group level.

840
00:29:36,540 --> 00:29:38,780
Policy handles the continuous enforcement

841
00:29:38,780 --> 00:29:40,780
at the subscription and resource level.

842
00:29:40,780 --> 00:29:42,540
Together they create a governance model

843
00:29:42,540 --> 00:29:45,580
that's declarative, auditable, and continuously enforced.

844
00:29:45,580 --> 00:29:47,340
This is where policy transitions from

845
00:29:47,340 --> 00:29:49,180
something the security team configures

846
00:29:49,180 --> 00:29:52,140
to something embedded in your organizational architecture.

847
00:29:52,140 --> 00:29:53,900
RBIAC and Identity as Code,

848
00:29:53,900 --> 00:29:56,060
role assignments are infrastructure.

849
00:29:56,060 --> 00:29:59,180
This is a statement that shifts how you think about access control.

850
00:29:59,180 --> 00:30:02,220
Not role assignments are managed by the security team.

851
00:30:02,220 --> 00:30:05,020
Not role assignments are configured in the portal.

852
00:30:05,020 --> 00:30:06,700
Role assignments are infrastructure.

853
00:30:06,700 --> 00:30:08,460
They should sit in bicep files.

854
00:30:08,460 --> 00:30:09,900
They should be versioned in Git.

855
00:30:09,900 --> 00:30:11,740
They should move through the same pipeline,

856
00:30:11,740 --> 00:30:13,660
validation, testing, approval

857
00:30:13,660 --> 00:30:16,140
that any other infrastructure change moves through.

858
00:30:16,140 --> 00:30:17,740
Because access is foundational,

859
00:30:17,740 --> 00:30:19,420
everything we've discussed up to this point,

860
00:30:19,420 --> 00:30:21,580
policies, modules, scopes, none of it matters

861
00:30:21,580 --> 00:30:24,380
if the people implementing it don't have the permissions to do so.

862
00:30:24,380 --> 00:30:26,860
And conversely, if people have access they shouldn't have,

863
00:30:26,860 --> 00:30:29,100
all the policies in the world won't prevent problems.

864
00:30:29,100 --> 00:30:31,900
Access control isn't a separate concern, it's infrastructure.

865
00:30:31,900 --> 00:30:35,020
The principle guiding this is lease privilege.

866
00:30:35,020 --> 00:30:37,260
You assign exactly the permissions needed

867
00:30:37,260 --> 00:30:38,860
at exactly the scope needed

868
00:30:38,860 --> 00:30:40,780
to exactly the identity that needs them.

869
00:30:40,780 --> 00:30:42,300
Not a role higher than required,

870
00:30:42,300 --> 00:30:43,900
not a scope broader than necessary.

871
00:30:43,900 --> 00:30:45,980
Not to an identity that doesn't actually need it.

872
00:30:45,980 --> 00:30:47,100
This sounds simple.

873
00:30:47,100 --> 00:30:48,380
In practice, it's the discipline

874
00:30:48,380 --> 00:30:50,540
that separates secure organizations from everyone else.

875
00:30:50,540 --> 00:30:53,340
There are three primary identity types you assign roles to

876
00:30:53,340 --> 00:30:56,060
and understanding the distinction changes your architecture.

877
00:30:56,060 --> 00:30:59,020
Service principles are identities you create and manage.

878
00:30:59,020 --> 00:31:01,980
They have credentials, passwords, or certificates.

879
00:31:01,980 --> 00:31:03,660
You're responsible for their life cycle,

880
00:31:03,660 --> 00:31:05,340
their rotation, their security.

881
00:31:05,340 --> 00:31:06,780
This is operational overhead.

882
00:31:06,780 --> 00:31:09,340
It's also why terraform and other tools need to store credentials

883
00:31:09,340 --> 00:31:10,780
to authenticate to Azure.

884
00:31:10,780 --> 00:31:13,820
Managed identities eliminate this category of operational burden.

885
00:31:13,820 --> 00:31:16,940
An Azure resource, a VM, a function app, a container

886
00:31:16,940 --> 00:31:18,860
gets a managed identity automatically.

887
00:31:18,860 --> 00:31:20,380
Azure manages the credentials.

888
00:31:20,380 --> 00:31:22,780
There's nothing to rotate, nothing to store and evolve.

889
00:31:22,780 --> 00:31:26,380
The resource can authenticate to Azure services using its identity.

890
00:31:26,380 --> 00:31:28,060
This is increasingly the preferred approach

891
00:31:28,060 --> 00:31:31,260
because it removes an entire class of operational problems.

892
00:31:31,260 --> 00:31:34,620
Azure AD groups, now Entra ID groups, are the third category.

893
00:31:34,620 --> 00:31:36,300
These are organizational identities,

894
00:31:36,300 --> 00:31:38,380
a group called platform team contains people.

895
00:31:38,380 --> 00:31:39,900
That group gets assigned a role.

896
00:31:39,900 --> 00:31:41,900
Now everyone in the group has that permission.

897
00:31:41,900 --> 00:31:44,860
When someone joins the team, they get added to the group.

898
00:31:44,860 --> 00:31:46,620
They automatically inherit the role.

899
00:31:46,620 --> 00:31:48,060
When they leave, they're removed.

900
00:31:48,060 --> 00:31:49,740
The role assignment doesn't change.

901
00:31:49,740 --> 00:31:53,100
You're managing team membership, not individual role assignments.

902
00:31:53,100 --> 00:31:55,660
The architecture question that surfaces here is this.

903
00:31:55,660 --> 00:31:56,860
Who can assign roles?

904
00:31:56,860 --> 00:31:59,180
And more specifically, who can assign roles at control?

905
00:31:59,180 --> 00:32:00,060
Who assigns roles?

906
00:32:00,060 --> 00:32:01,980
This is where RBAC becomes recursive.

907
00:32:01,980 --> 00:32:04,460
You need role assignments to govern role assignments.

908
00:32:04,460 --> 00:32:06,540
At the top, someone has owner at the tenant route.

909
00:32:06,540 --> 00:32:07,980
That's a hard starting point.

910
00:32:07,980 --> 00:32:10,220
Someone has to have ultimate permissions somewhere.

911
00:32:10,220 --> 00:32:11,660
But from there, you can delegate.

912
00:32:11,660 --> 00:32:13,500
The owner assigns owner to a platform team

913
00:32:13,500 --> 00:32:14,940
at the platform management group.

914
00:32:14,940 --> 00:32:17,020
The platform team can now assign roles to others

915
00:32:17,020 --> 00:32:18,220
at that scope and below.

916
00:32:18,220 --> 00:32:19,180
But not above.

917
00:32:19,180 --> 00:32:21,020
This creates a hierarchy of control.

918
00:32:21,020 --> 00:32:23,980
A ladder of delegation that mirrors organizational authority.

919
00:32:23,980 --> 00:32:25,260
When you codify this in BICEP,

920
00:32:25,260 --> 00:32:28,780
you're making those delegation decisions explicit and auditable.

921
00:32:28,780 --> 00:32:30,540
A BICEP file at management group

922
00:32:30,540 --> 00:32:32,460
scope that assigns roles to the platform team.

923
00:32:32,460 --> 00:32:34,540
That's a policy decision documented in code,

924
00:32:34,540 --> 00:32:37,340
reviewable in a pull request, traceable in audit logs.

925
00:32:37,340 --> 00:32:39,660
If someone later asks, why does the platform team

926
00:32:39,660 --> 00:32:41,020
have these permissions?

927
00:32:41,020 --> 00:32:42,540
You have a git history explaining

928
00:32:42,540 --> 00:32:45,020
when and why the decision was made.

929
00:32:45,020 --> 00:32:47,660
Managed identities shift this dynamic further.

930
00:32:47,660 --> 00:32:50,300
A BICEP file can create a managed identity,

931
00:32:50,300 --> 00:32:53,020
assign its specific roles at specific scopes,

932
00:32:53,020 --> 00:32:55,740
and embed it directly in the infrastructure definition.

933
00:32:55,740 --> 00:32:58,140
Now the application has exactly the permissions it needs.

934
00:32:58,140 --> 00:32:59,580
No more, no less.

935
00:32:59,580 --> 00:33:00,700
The application isn't running

936
00:33:00,700 --> 00:33:02,540
with an over-privileged service principle.

937
00:33:02,540 --> 00:33:03,980
It's running with an identity purpose

938
00:33:03,980 --> 00:33:05,020
built for its needs.

939
00:33:05,020 --> 00:33:06,940
Identity governance only works at scale.

940
00:33:06,940 --> 00:33:09,500
If it's codified, if it's infrastructure,

941
00:33:09,500 --> 00:33:13,900
Azure verified modules, AVM, the standardization framework.

942
00:33:13,900 --> 00:33:16,540
Up to this point, we've been building the architecture,

943
00:33:16,540 --> 00:33:20,140
scopes, parameters, modules, deployment stacks.

944
00:33:20,140 --> 00:33:22,300
But there's a critical question that hasn't been answered.

945
00:33:22,300 --> 00:33:24,060
Where do these modules come from?

946
00:33:24,060 --> 00:33:26,780
Does every organization start from scratch and build their own

947
00:33:26,780 --> 00:33:28,540
or is there a foundation to build on?

948
00:33:28,540 --> 00:33:30,220
AVM is Microsoft's answer,

949
00:33:30,220 --> 00:33:32,380
and it changes the conversation fundamentally.

950
00:33:32,380 --> 00:33:34,140
AVM stands for Azure verified modules.

951
00:33:34,140 --> 00:33:35,900
It's not a tool, it's not a service.

952
00:33:35,900 --> 00:33:37,100
It's a specification.

953
00:33:37,100 --> 00:33:39,340
A formal definition of what a production-ready module

954
00:33:39,340 --> 00:33:41,340
looks like across both bicep and terraform.

955
00:33:41,340 --> 00:33:42,700
This convergence is significant.

956
00:33:42,700 --> 00:33:44,060
It means your architectural standards

957
00:33:44,060 --> 00:33:45,500
don't have to choose a language.

958
00:33:45,500 --> 00:33:47,900
They can live above the implementation details.

959
00:33:47,900 --> 00:33:49,020
Here's why that matters.

960
00:33:49,020 --> 00:33:50,940
Organizations traditionally face the choice.

961
00:33:50,940 --> 00:33:52,220
Build your modules in terraform

962
00:33:52,220 --> 00:33:53,500
because you're multi-cloud.

963
00:33:53,500 --> 00:33:55,980
Build your modules in bicep because you're Azure native.

964
00:33:55,980 --> 00:33:58,220
Either way, you're building from first principles.

965
00:33:58,220 --> 00:34:00,220
You're deciding what parameters look like,

966
00:34:00,220 --> 00:34:01,820
how outputs are structured,

967
00:34:01,820 --> 00:34:03,740
what security defaults are non-negotiable,

968
00:34:03,740 --> 00:34:05,180
you're reinventing the wheel.

969
00:34:05,180 --> 00:34:07,180
Different teams in the same organization

970
00:34:07,180 --> 00:34:08,460
build modules differently

971
00:34:08,460 --> 00:34:09,740
because there's no shared standard

972
00:34:09,740 --> 00:34:10,940
for what different means.

973
00:34:10,940 --> 00:34:12,300
AVM changes this.

974
00:34:12,300 --> 00:34:14,060
Microsoft has already done the thinking.

975
00:34:14,060 --> 00:34:16,700
They've looked at what a production storage account needs.

976
00:34:16,700 --> 00:34:18,860
They've looked at what a secure virtual network requires.

977
00:34:18,860 --> 00:34:20,380
They've looked at what a compliant

978
00:34:20,380 --> 00:34:21,660
AKS cluster looks like.

979
00:34:21,660 --> 00:34:23,660
They've encoded all of that into modules.

980
00:34:23,660 --> 00:34:25,180
And this is the part that matters.

981
00:34:25,180 --> 00:34:27,420
They've done it in both bicep and terraform

982
00:34:27,420 --> 00:34:30,220
simultaneously following the same specification.

983
00:34:30,220 --> 00:34:32,700
The resource modules are the foundational layer.

984
00:34:32,700 --> 00:34:34,300
These wrap single resources,

985
00:34:34,300 --> 00:34:36,140
a storage account, a virtual network,

986
00:34:36,140 --> 00:34:37,260
an app service plan.

987
00:34:37,260 --> 00:34:40,060
But they wrap them with security defaults already applied.

988
00:34:40,060 --> 00:34:41,500
You can't create a storage account

989
00:34:41,500 --> 00:34:43,020
through the AVM resource module

990
00:34:43,020 --> 00:34:44,540
without encryption enabled.

991
00:34:44,540 --> 00:34:46,940
You can't deploy a network without the required

992
00:34:46,940 --> 00:34:48,460
network security groups.

993
00:34:48,460 --> 00:34:50,540
The module has already made the hard decisions.

994
00:34:50,540 --> 00:34:53,100
Your job isn't to decide if encryption matters.

995
00:34:53,100 --> 00:34:55,100
Your job is to choose where the data lives.

996
00:34:55,100 --> 00:34:56,700
Pattern modules go a layer higher.

997
00:34:56,700 --> 00:34:58,540
These orchestrate multiple resources

998
00:34:58,540 --> 00:34:59,980
into recognized architectures,

999
00:34:59,980 --> 00:35:01,340
a hub-spoken network,

1000
00:35:01,340 --> 00:35:02,380
a landing zone,

1001
00:35:02,380 --> 00:35:05,180
a secure Kubernetes cluster with all its prerequisites.

1002
00:35:05,180 --> 00:35:07,980
These modules aren't designed to be universally applicable.

1003
00:35:07,980 --> 00:35:09,580
They're designed to be foundational.

1004
00:35:09,580 --> 00:35:10,860
You don't use them unchanged.

1005
00:35:10,860 --> 00:35:12,140
You use them as starting points.

1006
00:35:12,140 --> 00:35:13,020
You customize them.

1007
00:35:13,020 --> 00:35:13,740
You extend them.

1008
00:35:13,740 --> 00:35:15,340
But you're not inventing the pattern.

1009
00:35:15,340 --> 00:35:16,380
You're inheriting it.

1010
00:35:16,380 --> 00:35:18,700
AVM also specifies the contract layer.

1011
00:35:18,700 --> 00:35:19,980
How parameters are named.

1012
00:35:19,980 --> 00:35:21,180
What outputs are guaranteed?

1013
00:35:21,180 --> 00:35:22,860
What documentation is required.

1014
00:35:22,860 --> 00:35:24,700
What testing standards apply?

1015
00:35:24,700 --> 00:35:26,060
This standardization matters

1016
00:35:26,060 --> 00:35:28,220
because it means a module built by Microsoft

1017
00:35:28,220 --> 00:35:29,660
follows the same conventions

1018
00:35:29,660 --> 00:35:31,580
as a module built by your platform team.

1019
00:35:31,580 --> 00:35:32,380
They fit together.

1020
00:35:32,380 --> 00:35:33,580
They can be composed.

1021
00:35:33,580 --> 00:35:35,180
They don't create a tower of Babel

1022
00:35:35,180 --> 00:35:37,180
where every module has a different interface.

1023
00:35:37,180 --> 00:35:38,380
The implication is profound.

1024
00:35:38,380 --> 00:35:40,140
You don't start from nothing.

1025
00:35:40,140 --> 00:35:42,620
You inherit Microsoft's architectural thinking

1026
00:35:42,620 --> 00:35:44,620
and customize it for your organization.

1027
00:35:44,620 --> 00:35:46,380
This isn't about taking shortcuts.

1028
00:35:46,380 --> 00:35:48,620
It's about not starting at the bottom of a mountain

1029
00:35:48,620 --> 00:35:50,140
that's already been climbed.

1030
00:35:50,140 --> 00:35:52,140
Microsoft has spent years understanding

1031
00:35:52,140 --> 00:35:54,860
how Azure resources should be configured securely,

1032
00:35:54,860 --> 00:35:56,860
resiliently, and operationally.

1033
00:35:56,860 --> 00:35:57,740
That work exists.

1034
00:35:57,740 --> 00:35:58,380
You can use it.

1035
00:35:58,380 --> 00:35:59,340
You can build on it.

1036
00:35:59,340 --> 00:36:00,300
You can modify it.

1037
00:36:00,300 --> 00:36:01,660
But you're not rediscovering it.

1038
00:36:01,660 --> 00:36:03,340
Versioning and maintenance reinforce this.

1039
00:36:03,340 --> 00:36:05,340
AVM modules are versioned,

1040
00:36:05,340 --> 00:36:07,180
semantic versioning, clear release notes,

1041
00:36:07,180 --> 00:36:08,460
deprecation parts.

1042
00:36:08,460 --> 00:36:09,980
When Azure releases a new feature,

1043
00:36:09,980 --> 00:36:11,580
Microsoft updates the module.

1044
00:36:11,580 --> 00:36:13,740
When a security vulnerability is discovered,

1045
00:36:13,740 --> 00:36:14,780
it gets patched.

1046
00:36:14,780 --> 00:36:15,980
When a best practice changes,

1047
00:36:15,980 --> 00:36:17,100
the module gets updated.

1048
00:36:17,100 --> 00:36:18,540
You don't maintain the module.

1049
00:36:18,540 --> 00:36:19,340
You consume it.

1050
00:36:19,340 --> 00:36:21,180
You update it when Microsoft updates it.

1051
00:36:21,180 --> 00:36:22,780
The organization publishing the module

1052
00:36:22,780 --> 00:36:24,460
is responsible for keeping it current.

1053
00:36:24,460 --> 00:36:27,020
This is where standardization leaves the realm of theory

1054
00:36:27,020 --> 00:36:28,300
and becomes operational.

1055
00:36:28,300 --> 00:36:30,940
You're not trying to convince teams that they should follow standards.

1056
00:36:30,940 --> 00:36:33,980
The standards are already built into the modules they're consuming.

1057
00:36:33,980 --> 00:36:35,900
Compliance isn't something they opt into.

1058
00:36:35,900 --> 00:36:37,980
It's the default behavior of the tool they're using.

1059
00:36:37,980 --> 00:36:40,620
This foundation AVM is what makes building

1060
00:36:40,620 --> 00:36:42,780
your organization's modules actually feasible.

1061
00:36:42,780 --> 00:36:45,580
You're not creating 70 resource modules from scratch.

1062
00:36:45,580 --> 00:36:47,020
You're wrapping AVM modules.

1063
00:36:47,020 --> 00:36:48,620
You're adding your naming standards,

1064
00:36:48,620 --> 00:36:50,140
your cost center requirements,

1065
00:36:50,140 --> 00:36:51,420
your monitoring baselines,

1066
00:36:51,420 --> 00:36:53,180
your customizing, not inventing.

1067
00:36:53,180 --> 00:36:55,580
That's when your modules become truly organizational.

1068
00:36:55,580 --> 00:36:57,740
Building your first module, the pattern.

1069
00:36:57,740 --> 00:36:59,500
So you understand the architecture.

1070
00:36:59,500 --> 00:37:00,620
You know why modules matter?

1071
00:37:00,620 --> 00:37:02,060
You've got AVM as a baseline.

1072
00:37:02,060 --> 00:37:03,820
Now you're sitting down to actually write one.

1073
00:37:03,820 --> 00:37:05,260
What does a production module look like?

1074
00:37:05,260 --> 00:37:06,060
There's a structure.

1075
00:37:06,060 --> 00:37:06,860
It's not arbitrary.

1076
00:37:06,860 --> 00:37:08,700
It's shaped by the needs of scale.

1077
00:37:08,700 --> 00:37:09,900
Start with the file layout.

1078
00:37:09,900 --> 00:37:12,140
Your module has a main file, main, bicep.

1079
00:37:12,140 --> 00:37:14,300
This is where the actual resource definitions live.

1080
00:37:14,300 --> 00:37:16,060
Before that, at the top of the file,

1081
00:37:16,060 --> 00:37:17,340
you declare your parameters.

1082
00:37:17,340 --> 00:37:18,460
These are the inputs.

1083
00:37:18,460 --> 00:37:20,860
The questions you're asking anyone who uses this module.

1084
00:37:20,860 --> 00:37:21,740
What's the location?

1085
00:37:21,740 --> 00:37:22,540
What's the environment?

1086
00:37:22,540 --> 00:37:23,500
What's the resource name?

1087
00:37:23,500 --> 00:37:24,860
What SKU do you want?

1088
00:37:24,860 --> 00:37:26,540
These parameter declarations come first

1089
00:37:26,540 --> 00:37:28,780
because they established a contract immediately.

1090
00:37:28,780 --> 00:37:30,700
Someone opening your module sees the parameters

1091
00:37:30,700 --> 00:37:32,380
and knows what decisions they need to make.

1092
00:37:32,380 --> 00:37:33,500
Parameters aren't loose.

1093
00:37:33,500 --> 00:37:34,700
You use decorators.

1094
00:37:34,700 --> 00:37:37,740
At min.3, because as you are required, is it?

1095
00:37:37,740 --> 00:37:40,140
At max.24, because as you're limited,

1096
00:37:40,140 --> 00:37:41,820
at a loud dev and test or prod,

1097
00:37:41,820 --> 00:37:44,620
because your organization only runs these three environments.

1098
00:37:44,620 --> 00:37:46,140
These constraints aren't restrictions.

1099
00:37:46,140 --> 00:37:46,940
They're clarity.

1100
00:37:46,940 --> 00:37:48,780
They're saying here's what's actually valid.

1101
00:37:48,780 --> 00:37:51,420
Here's what makes sense given our organizational constraints.

1102
00:37:51,420 --> 00:37:52,380
Next come variables.

1103
00:37:52,380 --> 00:37:53,900
Variables are where the module thinks.

1104
00:37:53,900 --> 00:37:55,820
If a parameter says environment,

1105
00:37:55,820 --> 00:37:58,380
a variable translates that into actual decisions.

1106
00:37:58,380 --> 00:37:59,740
If the environment is prod,

1107
00:37:59,740 --> 00:38:01,740
the variable sets the SKU to premium.

1108
00:38:01,740 --> 00:38:04,380
If it's dev, standard, if it's prod, backups run daily.

1109
00:38:04,380 --> 00:38:05,820
If it's dev, weekly.

1110
00:38:05,820 --> 00:38:07,580
The variable is where business logic lives.

1111
00:38:07,580 --> 00:38:09,420
It's where you say given these inputs,

1112
00:38:09,420 --> 00:38:10,780
here's what actually matters.

1113
00:38:10,780 --> 00:38:11,900
Then resources.

1114
00:38:11,900 --> 00:38:13,500
These are the actual Azure objects,

1115
00:38:13,500 --> 00:38:15,260
but notice they're parameterized.

1116
00:38:15,260 --> 00:38:17,020
The resource name uses parameters.

1117
00:38:17,020 --> 00:38:18,540
The location uses parameters.

1118
00:38:18,540 --> 00:38:21,340
The tags use variables that consumed parameters.

1119
00:38:21,340 --> 00:38:23,500
The same module file works in dev and prod.

1120
00:38:23,500 --> 00:38:25,260
The only difference is the parameter file.

1121
00:38:25,260 --> 00:38:26,540
The biceps stays the same.

1122
00:38:26,540 --> 00:38:27,980
This is where portability lives.

1123
00:38:27,980 --> 00:38:30,140
Outputs come at the end, but here's the discipline.

1124
00:38:30,140 --> 00:38:31,020
Minimize them.

1125
00:38:31,020 --> 00:38:32,940
Every output you expose is a promise.

1126
00:38:32,940 --> 00:38:35,260
It's saying downstream modules can rely on this.

1127
00:38:35,260 --> 00:38:37,980
If you remove it later, you break downstream code.

1128
00:38:37,980 --> 00:38:39,180
The tighter your outputs,

1129
00:38:39,180 --> 00:38:41,260
the more freedom you have to refactor the module

1130
00:38:41,260 --> 00:38:42,460
without breaking consumers.

1131
00:38:42,460 --> 00:38:44,220
Output the resource idea if it's needed.

1132
00:38:44,220 --> 00:38:46,940
Output important properties if they're genuinely necessary.

1133
00:38:46,940 --> 00:38:48,140
Don't output everything.

1134
00:38:48,140 --> 00:38:50,380
Expose only what's architecturally necessary.

1135
00:38:50,380 --> 00:38:51,740
Documentation is not optional.

1136
00:38:51,740 --> 00:38:52,940
It's part of the module.

1137
00:38:52,940 --> 00:38:54,940
Every production module has a readme.

1138
00:38:54,940 --> 00:38:56,060
This isn't a formality.

1139
00:38:56,060 --> 00:38:57,660
It's operational necessity.

1140
00:38:57,660 --> 00:38:59,660
The readme explains what this module does.

1141
00:38:59,660 --> 00:39:00,780
What problem it solves.

1142
00:39:00,780 --> 00:39:01,980
What parameters mean.

1143
00:39:01,980 --> 00:39:03,260
What outputs you get.

1144
00:39:03,260 --> 00:39:05,180
What assumptions it makes about your environment.

1145
00:39:05,180 --> 00:39:07,260
If your organization requires cost center tags,

1146
00:39:07,260 --> 00:39:08,540
the readme says that.

1147
00:39:08,540 --> 00:39:10,540
If the module only works on certain Azure regions,

1148
00:39:10,540 --> 00:39:11,500
the readme lists them.

1149
00:39:11,500 --> 00:39:13,020
If there are security implications,

1150
00:39:13,020 --> 00:39:14,380
the readme explains them.

1151
00:39:14,380 --> 00:39:16,860
Someone new to your team picks up a module.

1152
00:39:16,860 --> 00:39:17,820
They read the readme.

1153
00:39:17,820 --> 00:39:19,020
They understand what it does.

1154
00:39:19,020 --> 00:39:20,700
They understand what it costs.

1155
00:39:20,700 --> 00:39:22,140
They understand what it requires.

1156
00:39:22,140 --> 00:39:23,180
They don't have to guess.

1157
00:39:23,180 --> 00:39:24,860
They don't have to reverse engineer.

1158
00:39:24,860 --> 00:39:26,780
Testing is a discipline that's often skipped.

1159
00:39:26,780 --> 00:39:27,260
Don't.

1160
00:39:27,260 --> 00:39:29,180
Bicep validate catches syntax errors.

1161
00:39:29,180 --> 00:39:29,660
Run it.

1162
00:39:29,660 --> 00:39:31,740
What if deployments show you what will actually be created

1163
00:39:31,740 --> 00:39:32,780
before you create it.

1164
00:39:32,780 --> 00:39:34,300
Run them in a test subscription.

1165
00:39:34,300 --> 00:39:35,900
Policy compliance checks validate

1166
00:39:35,900 --> 00:39:38,780
that whatever you deploy will pass your organizational policies.

1167
00:39:38,780 --> 00:39:39,500
Run them.

1168
00:39:39,500 --> 00:39:41,180
If your module creates a storage account

1169
00:39:41,180 --> 00:39:43,020
that would fail your encryption policy,

1170
00:39:43,020 --> 00:39:45,020
you want to know invalidation not in production.

1171
00:39:45,020 --> 00:39:47,820
A production module is structured, documented, tested.

1172
00:39:47,820 --> 00:39:48,860
It's not a one-time script.

1173
00:39:48,860 --> 00:39:50,940
It's infrastructure that other teams will build on.

1174
00:39:50,940 --> 00:39:54,300
It's infrastructure that your organization will rely on for years.

1175
00:39:54,300 --> 00:39:56,460
That structure is where theoretical architecture

1176
00:39:56,460 --> 00:39:58,140
becomes practical reality.

1177
00:39:58,140 --> 00:40:00,300
Module, registries, and governance.

1178
00:40:00,300 --> 00:40:01,740
Modules need to live somewhere.

1179
00:40:01,740 --> 00:40:04,380
This sounds obvious until you're standing in an organization

1180
00:40:04,380 --> 00:40:08,060
with 50 modules scattered across five different Git repositories

1181
00:40:08,060 --> 00:40:09,900
three owned by the platform team,

1182
00:40:09,900 --> 00:40:11,660
two owned by application teams,

1183
00:40:11,660 --> 00:40:13,180
non-versioned consistently,

1184
00:40:13,180 --> 00:40:15,660
half of them duplicating the work of the other half.

1185
00:40:15,660 --> 00:40:18,460
Azure Container Registry is the standard for bicep modules.

1186
00:40:18,460 --> 00:40:19,820
This isn't a technical requirement.

1187
00:40:19,820 --> 00:40:21,580
You could host bicep files anywhere,

1188
00:40:21,580 --> 00:40:24,380
but ACR becomes the mechanism for centralizing,

1189
00:40:24,380 --> 00:40:27,020
versioning, and controlling access to your module library.

1190
00:40:27,020 --> 00:40:29,340
It's not just storage, it's governance infrastructure.

1191
00:40:29,340 --> 00:40:32,380
When teams publish modules to ACR,

1192
00:40:32,380 --> 00:40:34,780
they are publishing to an internal marketplace.

1193
00:40:34,780 --> 00:40:36,140
This isn't marketing language.

1194
00:40:36,140 --> 00:40:37,260
It's operational reality.

1195
00:40:37,260 --> 00:40:38,700
Teams need to discover modules.

1196
00:40:38,700 --> 00:40:40,300
They need to know what exists.

1197
00:40:40,300 --> 00:40:41,820
They need to know what's safe to use.

1198
00:40:41,820 --> 00:40:44,940
They need to know if a module is actively maintained or deprecated.

1199
00:40:44,940 --> 00:40:46,300
A registry becomes the interface

1200
00:40:46,300 --> 00:40:49,420
through which your organization communicates about infrastructure standards.

1201
00:40:49,420 --> 00:40:52,540
Someone on an application team is building a new resource group.

1202
00:40:52,540 --> 00:40:53,900
They need a virtual network.

1203
00:40:53,900 --> 00:40:55,580
They could write one from scratch.

1204
00:40:55,580 --> 00:40:57,420
Or they could go to the module registry

1205
00:40:57,420 --> 00:41:00,140
see that the platform team has published a network module,

1206
00:41:00,140 --> 00:41:02,620
read the documentation, understand what it provides,

1207
00:41:02,620 --> 00:41:04,140
and use it.

1208
00:41:04,140 --> 00:41:05,980
That moment, where they discover the standard

1209
00:41:05,980 --> 00:41:07,260
instead of inventing their own,

1210
00:41:07,260 --> 00:41:09,020
that's where governance stops being theoretical

1211
00:41:09,020 --> 00:41:10,380
and becomes practical.

1212
00:41:10,380 --> 00:41:12,860
Versioning is where the rubber meets the road.

1213
00:41:12,860 --> 00:41:15,500
Semantic versioning, major minor patch.

1214
00:41:15,500 --> 00:41:17,500
If the platform team makes a breaking change

1215
00:41:17,500 --> 00:41:20,220
to the network module, maybe they change how subnets are named

1216
00:41:20,220 --> 00:41:21,500
or alter the output structure.

1217
00:41:21,500 --> 00:41:23,180
That's a major version bump.

1218
00:41:23,180 --> 00:41:26,620
Version 2.0, everyone consuming version 1.0 keeps working.

1219
00:41:26,620 --> 00:41:27,900
They're not forced to update.

1220
00:41:27,900 --> 00:41:30,220
When they're ready, they plan the upgrade, they test it.

1221
00:41:30,220 --> 00:41:32,380
They move to 2.0 on their schedule.

1222
00:41:32,380 --> 00:41:33,660
The alternative is chaos.

1223
00:41:33,660 --> 00:41:35,340
You publish a new version of a module.

1224
00:41:35,340 --> 00:41:37,340
Suddenly 10 teams have breaking code.

1225
00:41:37,340 --> 00:41:38,140
Pipelines fail.

1226
00:41:38,140 --> 00:41:38,860
Production fails.

1227
00:41:38,860 --> 00:41:40,540
People stay awake at 2am debugging

1228
00:41:40,540 --> 00:41:41,900
why their infrastructure won't deploy.

1229
00:41:41,900 --> 00:41:42,700
That's not governance.

1230
00:41:42,700 --> 00:41:43,660
That's sabotage.

1231
00:41:43,660 --> 00:41:45,340
Semantic versioning prevents this.

1232
00:41:45,340 --> 00:41:47,260
Consumers pin to specific versions.

1233
00:41:47,260 --> 00:41:48,700
They control when they upgrade.

1234
00:41:48,700 --> 00:41:50,380
Breaking changes require planning.

1235
00:41:50,380 --> 00:41:53,020
Access control around the registry is governance itself.

1236
00:41:53,020 --> 00:41:54,620
Who can publish modules to ACR?

1237
00:41:54,620 --> 00:41:55,180
Not everyone.

1238
00:41:55,180 --> 00:41:56,140
This isn't gatekeeping.

1239
00:41:56,140 --> 00:41:57,260
It's accountability.

1240
00:41:57,260 --> 00:41:59,660
If anyone can publish, the registry becomes polluted.

1241
00:41:59,660 --> 00:42:01,340
People publish incomplete modules.

1242
00:42:01,340 --> 00:42:02,620
Modules with security holes.

1243
00:42:02,620 --> 00:42:04,940
Modules that conflict with organizational standards.

1244
00:42:04,940 --> 00:42:06,540
You need a publication process.

1245
00:42:06,540 --> 00:42:08,700
Someone reviews the module before it's published.

1246
00:42:08,700 --> 00:42:10,220
Does it follow naming conventions?

1247
00:42:10,220 --> 00:42:11,820
Does it include documentation?

1248
00:42:11,820 --> 00:42:13,580
Does it pass security scanning?

1249
00:42:13,580 --> 00:42:15,660
Does it align with organizational constraints?

1250
00:42:15,660 --> 00:42:17,180
The review isn't bureaucracy.

1251
00:42:17,180 --> 00:42:18,620
It's quality control.

1252
00:42:18,620 --> 00:42:20,140
It's the moment someone says,

1253
00:42:20,140 --> 00:42:22,460
this module represents how our organization

1254
00:42:22,460 --> 00:42:23,340
does infrastructure.

1255
00:42:23,340 --> 00:42:24,860
That's not something you delegate to

1256
00:42:24,860 --> 00:42:26,380
whoever feels like publishing.

1257
00:42:26,380 --> 00:42:28,220
The registry becomes the source of truth

1258
00:42:28,220 --> 00:42:29,420
for a single question.

1259
00:42:29,420 --> 00:42:31,580
How do we do infrastructure in this organization?

1260
00:42:31,580 --> 00:42:33,420
Not how the security team thinks we should.

1261
00:42:33,420 --> 00:42:35,660
Not how the platform team hopes we will.

1262
00:42:35,660 --> 00:42:36,700
How we actually do?

1263
00:42:36,700 --> 00:42:39,260
The answer lives in the modules published to that registry.

1264
00:42:39,260 --> 00:42:40,860
The versions, the documentation,

1265
00:42:40,860 --> 00:42:43,340
the decisions encoded in parameters and variables.

1266
00:42:43,340 --> 00:42:44,860
Module deprecation is a process

1267
00:42:44,860 --> 00:42:47,740
that most organizations skip and then regret.

1268
00:42:47,740 --> 00:42:49,420
Old modules accumulate.

1269
00:42:49,420 --> 00:42:51,500
Version 1.0 of a pattern that got replaced

1270
00:42:51,500 --> 00:42:53,580
by version 3.0 three years ago

1271
00:42:53,580 --> 00:42:55,100
still sits in the registry.

1272
00:42:55,100 --> 00:42:56,460
Teams don't know if they should use it.

1273
00:42:56,460 --> 00:42:58,060
The platform team doesn't know if anyone's

1274
00:42:58,060 --> 00:42:59,180
still depending on it.

1275
00:42:59,180 --> 00:43:00,860
When they finally decide to remove it,

1276
00:43:00,860 --> 00:43:02,460
they break someone's pipeline.

1277
00:43:02,460 --> 00:43:03,980
Proper deprecation works differently.

1278
00:43:03,980 --> 00:43:06,380
You mark a module as deprecated in the registry.

1279
00:43:06,380 --> 00:43:08,620
The documentation makes clear what the replacement is.

1280
00:43:08,620 --> 00:43:10,140
You give teams a window to migrate.

1281
00:43:10,140 --> 00:43:10,860
Six months.

1282
00:43:10,860 --> 00:43:12,140
A year, whatever makes sense.

1283
00:43:12,140 --> 00:43:13,420
Then you remove the old version.

1284
00:43:13,420 --> 00:43:14,220
Everyone's had time.

1285
00:43:14,220 --> 00:43:15,660
Everyone knows the path forward.

1286
00:43:15,660 --> 00:43:17,980
Deprecation is part of the life cycle discipline.

1287
00:43:17,980 --> 00:43:19,900
The registry isn't just where modules live.

1288
00:43:19,900 --> 00:43:22,220
It's where governance becomes visible and operational.

1289
00:43:22,220 --> 00:43:23,820
Landing zones.

1290
00:43:23,820 --> 00:43:25,420
The architectural blueprint.

1291
00:43:25,420 --> 00:43:27,100
Everything we've covered up to this point.

1292
00:43:27,100 --> 00:43:29,100
Modules, policies, scopes,

1293
00:43:29,100 --> 00:43:31,900
life cycle management converges in a single place.

1294
00:43:31,900 --> 00:43:32,620
The landing zone.

1295
00:43:32,620 --> 00:43:34,220
This is where theory becomes the environment

1296
00:43:34,220 --> 00:43:35,500
that teams actually work in.

1297
00:43:35,500 --> 00:43:37,260
A landing zone is a pre-configured

1298
00:43:37,260 --> 00:43:38,300
Azure subscription.

1299
00:43:38,300 --> 00:43:39,260
Not a resource group.

1300
00:43:39,260 --> 00:43:41,900
Not a collection of resources floating somewhere.

1301
00:43:41,900 --> 00:43:44,620
A complete subscription that's ready for workloads to run.

1302
00:43:44,620 --> 00:43:46,860
Someone from an application team comes to you and says,

1303
00:43:46,860 --> 00:43:48,460
"We need cloud infrastructure."

1304
00:43:48,460 --> 00:43:49,660
You hand them a landing zone.

1305
00:43:49,660 --> 00:43:50,940
They don't get an empty subscription

1306
00:43:50,940 --> 00:43:53,180
with a task list of things they need to configure.

1307
00:43:53,180 --> 00:43:55,660
They get a subscription where everything's already there.

1308
00:43:55,660 --> 00:43:57,340
Here's what already there actually means.

1309
00:43:57,340 --> 00:43:59,100
Network isolation.

1310
00:43:59,100 --> 00:44:01,420
They've got a virtual network with the correct subnets

1311
00:44:01,420 --> 00:44:02,860
for their application to your structure.

1312
00:44:02,860 --> 00:44:05,340
They've got network security groups already configured

1313
00:44:05,340 --> 00:44:06,300
with baseline rules.

1314
00:44:06,300 --> 00:44:07,500
They've got root tables.

1315
00:44:07,500 --> 00:44:09,740
If they need to integrate with on-premises.

1316
00:44:09,740 --> 00:44:11,500
They're not starting with blank networking.

1317
00:44:11,500 --> 00:44:12,780
They're starting with a foundation

1318
00:44:12,780 --> 00:44:14,620
that matches organizational standards.

1319
00:44:14,620 --> 00:44:16,540
Identity integration works the same way.

1320
00:44:16,540 --> 00:44:17,980
Enter IDs already connected.

1321
00:44:17,980 --> 00:44:21,180
The subscription is discoverable within the organization's directory.

1322
00:44:21,180 --> 00:44:23,820
Users have the right permissions to deploy resources.

1323
00:44:23,820 --> 00:44:25,580
Application identities can authenticate

1324
00:44:25,580 --> 00:44:28,060
without anyone manually wiring credentials.

1325
00:44:28,060 --> 00:44:29,660
Service principles are pre-configured

1326
00:44:29,660 --> 00:44:31,180
if the application needs them.

1327
00:44:31,180 --> 00:44:33,180
Identity isn't a puzzle the team solves.

1328
00:44:33,180 --> 00:44:34,940
It's a solved problem they inherit.

1329
00:44:34,940 --> 00:44:36,700
Policy baseline is already applied.

1330
00:44:36,700 --> 00:44:39,100
The policies you've defined at the management group level

1331
00:44:39,100 --> 00:44:40,220
are already active.

1332
00:44:40,220 --> 00:44:41,100
But more than that,

1333
00:44:41,100 --> 00:44:43,020
there might be subscription level policies

1334
00:44:43,020 --> 00:44:45,020
applied specifically to this landing zone.

1335
00:44:45,020 --> 00:44:47,500
If it's a production zone, stricter enforcement.

1336
00:44:47,500 --> 00:44:50,060
If it's a sandbox zone, more permissive rules.

1337
00:44:50,060 --> 00:44:53,180
The landing zone comes with the right policy posture built in.

1338
00:44:53,180 --> 00:44:54,300
Monitoring is wired.

1339
00:44:54,300 --> 00:44:56,380
Log analytics workspace is already there.

1340
00:44:56,380 --> 00:44:58,300
Diagnostic settings are already configured

1341
00:44:58,300 --> 00:45:01,100
so that anything created gets automatically logged.

1342
00:45:01,100 --> 00:45:02,140
If something breaks,

1343
00:45:02,140 --> 00:45:04,060
you've got the data to understand why.

1344
00:45:04,060 --> 00:45:05,500
Monitoring isn't something the team

1345
00:45:05,500 --> 00:45:06,860
configures after they've been running

1346
00:45:06,860 --> 00:45:08,220
for six months and things go wrong.

1347
00:45:08,220 --> 00:45:09,580
It's there from day one.

1348
00:45:09,580 --> 00:45:11,340
The distinction matters between two types.

1349
00:45:11,340 --> 00:45:13,820
Platform landing zones are shared infrastructure.

1350
00:45:13,820 --> 00:45:15,340
This is where the hub network lives

1351
00:45:15,340 --> 00:45:16,540
if you're doing hub and spoke.

1352
00:45:16,540 --> 00:45:18,060
This is where shared services run.

1353
00:45:18,060 --> 00:45:21,180
Directory services, DNS, backup systems.

1354
00:45:21,180 --> 00:45:23,420
These are the subscriptions the platform team runs.

1355
00:45:23,420 --> 00:45:24,860
Application teams don't touch them.

1356
00:45:24,860 --> 00:45:27,180
They just consume the services and the connectivity.

1357
00:45:27,180 --> 00:45:29,340
Application landing zones are workloads specific.

1358
00:45:29,340 --> 00:45:31,420
This is where the actual application infrastructure

1359
00:45:31,420 --> 00:45:31,980
lives.

1360
00:45:31,980 --> 00:45:34,940
The databases, the compute, the storage for user data.

1361
00:45:34,940 --> 00:45:36,780
Each application team gets their landing zone.

1362
00:45:36,780 --> 00:45:38,540
It's isolated from other teams.

1363
00:45:38,540 --> 00:45:41,260
But it's integrated with the shared platform services.

1364
00:45:41,260 --> 00:45:43,740
Network connectivity flows through the hub.

1365
00:45:43,740 --> 00:45:45,980
Logs flow to the central log analytics.

1366
00:45:45,980 --> 00:45:48,620
Identity flows through the organizational directory.

1367
00:45:48,620 --> 00:45:50,540
Bicep is how you define all of this.

1368
00:45:50,540 --> 00:45:53,100
A landing zone template isn't a single bicep file.

1369
00:45:53,100 --> 00:45:54,380
It's a composition of modules.

1370
00:45:54,380 --> 00:45:56,300
The network module, the policy module,

1371
00:45:56,300 --> 00:45:57,340
the monitoring module,

1372
00:45:57,340 --> 00:45:59,180
the identity integration module,

1373
00:45:59,180 --> 00:46:00,940
all orchestrated at subscription scope.

1374
00:46:00,940 --> 00:46:02,380
You write a landing zone template

1375
00:46:02,380 --> 00:46:05,340
that says create a subscription with these characteristics.

1376
00:46:05,340 --> 00:46:06,780
Create its networking.

1377
00:46:06,780 --> 00:46:08,300
Assign its policies.

1378
00:46:08,300 --> 00:46:09,740
Why are its monitoring?

1379
00:46:09,740 --> 00:46:11,020
Integrate its identity.

1380
00:46:11,020 --> 00:46:13,820
Here's where the architectural question surfaces.

1381
00:46:13,820 --> 00:46:15,420
Are you building one landing zone,

1382
00:46:15,420 --> 00:46:18,140
a static subscription you hand to a specific team?

1383
00:46:18,140 --> 00:46:19,340
Or are you building a template

1384
00:46:19,340 --> 00:46:21,580
that can be instantiated many times?

1385
00:46:21,580 --> 00:46:23,740
The answer determines your entire approach.

1386
00:46:23,740 --> 00:46:25,980
If it's static, you can hard code decisions.

1387
00:46:25,980 --> 00:46:27,020
If it's a template,

1388
00:46:27,020 --> 00:46:28,780
every decision needs to be parameterized.

1389
00:46:28,780 --> 00:46:30,140
What's the naming convention?

1390
00:46:30,140 --> 00:46:32,220
What network range does this landing zone use?

1391
00:46:32,220 --> 00:46:33,660
How does it connect to the hub?

1392
00:46:33,660 --> 00:46:35,100
What policy baseline applies?

1393
00:46:35,100 --> 00:46:36,380
What monitoring retention?

1394
00:46:36,380 --> 00:46:38,540
These become parameters in your landing zone template.

1395
00:46:38,540 --> 00:46:39,420
Azure Landing Zones,

1396
00:46:39,420 --> 00:46:41,660
the ALZ reference architecture from Microsoft,

1397
00:46:41,660 --> 00:46:42,860
provides the blueprint.

1398
00:46:42,860 --> 00:46:44,860
It's not a template you use unchanged.

1399
00:46:44,860 --> 00:46:45,500
It's a reference.

1400
00:46:45,500 --> 00:46:48,140
It shows you what a well-designed landing zone looks like.

1401
00:46:48,140 --> 00:46:49,580
What components are essential?

1402
00:46:49,580 --> 00:46:50,780
How they fit together?

1403
00:46:50,780 --> 00:46:52,540
What security principles guide the design?

1404
00:46:52,540 --> 00:46:53,900
You take that reference

1405
00:46:53,900 --> 00:46:55,980
and customize it for your organization.

1406
00:46:55,980 --> 00:46:57,100
Your naming standards,

1407
00:46:57,100 --> 00:46:58,540
your network architecture,

1408
00:46:58,540 --> 00:46:59,580
your policy model,

1409
00:46:59,580 --> 00:47:01,580
your identity integration patterns.

1410
00:47:01,580 --> 00:47:03,180
The landing zone becomes the artifact

1411
00:47:03,180 --> 00:47:05,980
where all your architectural decisions become real infrastructure.

1412
00:47:05,980 --> 00:47:06,700
It's not a theory.

1413
00:47:06,700 --> 00:47:07,740
It's not a diagram.

1414
00:47:07,740 --> 00:47:10,060
It's a subscription that teams actually work in.

1415
00:47:10,060 --> 00:47:11,340
Every team that gets a landing zone

1416
00:47:11,340 --> 00:47:12,780
gets the same governance model.

1417
00:47:12,780 --> 00:47:14,620
The same standards, the same controls.

1418
00:47:14,620 --> 00:47:15,580
That's not limiting.

1419
00:47:15,580 --> 00:47:16,620
That's consistency.

1420
00:47:16,620 --> 00:47:18,220
That's the moment your architecture

1421
00:47:18,220 --> 00:47:19,500
stops being aspirational

1422
00:47:19,500 --> 00:47:21,340
and starts being operational.

1423
00:47:21,340 --> 00:47:22,860
Multi-environment deployments.

1424
00:47:22,860 --> 00:47:23,820
Dev test.

1425
00:47:23,820 --> 00:47:24,460
Prod.

1426
00:47:24,460 --> 00:47:27,020
Here's the moment where theory meets operational reality.

1427
00:47:27,020 --> 00:47:27,820
You've built modules.

1428
00:47:27,820 --> 00:47:28,780
You've got them published.

1429
00:47:28,780 --> 00:47:30,060
You've got a landing zone template

1430
00:47:30,060 --> 00:47:31,500
that orchestrates everything.

1431
00:47:31,500 --> 00:47:33,020
Now you need to deploy it three times.

1432
00:47:33,020 --> 00:47:33,900
Once for development.

1433
00:47:33,900 --> 00:47:34,620
Once for testing.

1434
00:47:34,620 --> 00:47:35,740
Once for production.

1435
00:47:35,740 --> 00:47:36,940
And you need to do this

1436
00:47:36,940 --> 00:47:39,340
without maintaining three separate bicep files.

1437
00:47:39,340 --> 00:47:40,780
The principle is straightforward.

1438
00:47:40,780 --> 00:47:43,340
The same template works across all three environments.

1439
00:47:43,340 --> 00:47:44,860
The difference is parameters.

1440
00:47:44,860 --> 00:47:46,940
You write one main bicep file.

1441
00:47:46,940 --> 00:47:48,780
This defines your infrastructure architecture.

1442
00:47:48,780 --> 00:47:50,060
What modules get composed,

1443
00:47:50,060 --> 00:47:51,100
how they fit together,

1444
00:47:51,100 --> 00:47:52,940
what the overall shape looks like.

1445
00:47:52,940 --> 00:47:54,700
This main file has parameters.

1446
00:47:54,700 --> 00:47:56,140
The decisions that need to be made.

1447
00:47:56,140 --> 00:47:57,740
Then you create three parameter files.

1448
00:47:57,740 --> 00:48:00,140
Bicep arm files.

1449
00:48:00,140 --> 00:48:01,180
One for dev.

1450
00:48:01,180 --> 00:48:02,060
One for test.

1451
00:48:02,060 --> 00:48:03,260
One for prod.

1452
00:48:03,260 --> 00:48:05,340
Each parameter file answers the same questions

1453
00:48:05,340 --> 00:48:06,140
differently.

1454
00:48:06,140 --> 00:48:08,220
What location should this infrastructure run in?

1455
00:48:08,220 --> 00:48:09,500
Dev might say US East.

1456
00:48:09,500 --> 00:48:11,020
Test might say US West.

1457
00:48:11,020 --> 00:48:13,020
Prod might say both with fail over configured.

1458
00:48:13,020 --> 00:48:14,620
What as you should the database be?

1459
00:48:14,620 --> 00:48:15,500
Dev might be standard.

1460
00:48:15,500 --> 00:48:16,540
Test might be standard.

1461
00:48:16,540 --> 00:48:17,500
Prod might be premium.

1462
00:48:17,500 --> 00:48:18,780
What's the backup frequency?

1463
00:48:18,780 --> 00:48:20,220
Dev might have no backups.

1464
00:48:20,220 --> 00:48:21,420
Test might have daily backups.

1465
00:48:21,420 --> 00:48:22,380
Prod might have hourly.

1466
00:48:22,380 --> 00:48:23,420
What network range?

1467
00:48:23,420 --> 00:48:26,460
Dev might use 10.0 open as a no 16.

1468
00:48:26,460 --> 00:48:28,780
Test might use 10.1 also 0.16.

1469
00:48:28,780 --> 00:48:30,300
Prod might use 10.2,

1470
00:48:30,300 --> 00:48:31,260
ampomo 16,

1471
00:48:31,260 --> 00:48:34,220
and 10.3 ampomo 16 for redundancy.

1472
00:48:34,220 --> 00:48:36,380
The bicep file is where you make decisions

1473
00:48:36,380 --> 00:48:38,380
about how infrastructure should be structured.

1474
00:48:38,380 --> 00:48:40,620
The parameter files are where you make decisions

1475
00:48:40,620 --> 00:48:43,020
about what level of that structure you're willing to pay for

1476
00:48:43,020 --> 00:48:44,620
and support in each environment.

1477
00:48:44,620 --> 00:48:45,980
Here's the discipline this requires.

1478
00:48:45,980 --> 00:48:48,300
Your bicep variables should encode defaults.

1479
00:48:48,300 --> 00:48:50,700
These defaults should reflect your baseline assumptions.

1480
00:48:50,700 --> 00:48:52,380
The minimum security posture.

1481
00:48:52,380 --> 00:48:53,580
The minimum monitoring.

1482
00:48:53,580 --> 00:48:55,740
The minimum resilience that you require everywhere.

1483
00:48:55,740 --> 00:48:57,820
Then parameters override those defaults

1484
00:48:57,820 --> 00:48:59,180
for specific environments.

1485
00:48:59,180 --> 00:49:00,860
If the environment is production,

1486
00:49:00,860 --> 00:49:03,980
the parameter file says upgrade the SKU.

1487
00:49:03,980 --> 00:49:05,420
Enable additional monitoring.

1488
00:49:05,420 --> 00:49:06,700
Configure failover.

1489
00:49:06,700 --> 00:49:08,140
If the environment is development,

1490
00:49:08,140 --> 00:49:11,420
the parameter file might say use the cheapest option available

1491
00:49:11,420 --> 00:49:13,580
that still meets compliance requirements.

1492
00:49:13,580 --> 00:49:15,420
The governance question surfaces immediately.

1493
00:49:15,420 --> 00:49:17,180
What's actually different between environments?

1494
00:49:17,180 --> 00:49:19,660
This seems obvious until you're standing in an organization

1495
00:49:19,660 --> 00:49:21,580
that has three copies of the same infrastructure

1496
00:49:21,580 --> 00:49:23,020
that diverged five years ago.

1497
00:49:23,020 --> 00:49:24,540
And nobody remembers why.

1498
00:49:24,540 --> 00:49:26,700
Dev has a feature enabled that test doesn't.

1499
00:49:26,700 --> 00:49:28,860
Prod is missing security controls that Dev has.

1500
00:49:28,860 --> 00:49:31,420
They're supposed to be the same architecture at different scales.

1501
00:49:31,420 --> 00:49:33,020
Instead, there are three different systems

1502
00:49:33,020 --> 00:49:34,940
that happen to run the same application.

1503
00:49:34,940 --> 00:49:37,500
Clear thinking about this prevents the divergence.

1504
00:49:37,500 --> 00:49:38,860
In most mature organizations,

1505
00:49:38,860 --> 00:49:41,260
the differences cluster around a few dimensions.

1506
00:49:41,260 --> 00:49:42,940
Access control is different.

1507
00:49:42,940 --> 00:49:46,380
Dev might allow anyone with a subscription contributor role to deploy.

1508
00:49:46,380 --> 00:49:47,980
Prod should require manual approvals

1509
00:49:47,980 --> 00:49:49,820
who gets access to prod databases.

1510
00:49:49,820 --> 00:49:52,620
Nobody on the dev team without explicit authorization.

1511
00:49:52,620 --> 00:49:55,980
These access differences need to be reflected in parameters.

1512
00:49:55,980 --> 00:49:58,060
Roll assignments, R-back constraints,

1513
00:49:58,060 --> 00:49:59,660
EntraID group memberships.

1514
00:49:59,660 --> 00:50:01,420
Monitoring verbosity is different.

1515
00:50:01,420 --> 00:50:04,300
Dev might log minimally just errors in critical warnings.

1516
00:50:04,300 --> 00:50:05,580
Test might log more.

1517
00:50:05,580 --> 00:50:07,820
Information level, warnings, errors,

1518
00:50:07,820 --> 00:50:09,180
prod might log everything,

1519
00:50:09,180 --> 00:50:11,980
including diagnostic data for performance analysis.

1520
00:50:11,980 --> 00:50:13,740
These translate into parameter decisions

1521
00:50:13,740 --> 00:50:16,700
about logging levels, retention periods, and alert thresholds.

1522
00:50:16,700 --> 00:50:18,060
Cost constraints are different.

1523
00:50:18,060 --> 00:50:19,740
You can experiment with expensive features

1524
00:50:19,740 --> 00:50:22,220
and dev scaling isn't usually necessary.

1525
00:50:22,220 --> 00:50:23,980
In prod, you want efficiency.

1526
00:50:23,980 --> 00:50:26,380
This means sizing decisions, database SKUs,

1527
00:50:26,380 --> 00:50:27,580
compute instance counts,

1528
00:50:27,580 --> 00:50:30,220
whether you're using reserved capacity or on demand.

1529
00:50:30,220 --> 00:50:31,740
Resilience requirements diverge.

1530
00:50:31,740 --> 00:50:32,940
Dev doesn't need failover.

1531
00:50:32,940 --> 00:50:35,340
Test might need failover between regions to validate it works.

1532
00:50:35,340 --> 00:50:36,620
Prod probably needs it.

1533
00:50:36,620 --> 00:50:38,700
This affects how many resources you deploy

1534
00:50:38,700 --> 00:50:39,820
and how they're configured.

1535
00:50:39,820 --> 00:50:43,660
The CIRCD pipeline validates each environment separately.

1536
00:50:43,660 --> 00:50:45,500
A deployment to production triggers a different flow

1537
00:50:45,500 --> 00:50:46,700
than a deployment to dev.

1538
00:50:46,700 --> 00:50:48,460
Production requires approvals.

1539
00:50:48,460 --> 00:50:50,140
Prod does policy validation.

1540
00:50:50,140 --> 00:50:51,580
Prod might require the template

1541
00:50:51,580 --> 00:50:53,420
to pass additional security scanning.

1542
00:50:53,420 --> 00:50:54,940
Dev might just need validation

1543
00:50:54,940 --> 00:50:56,380
that the syntax is correct.

1544
00:50:56,380 --> 00:50:57,740
The payoff is enormous.

1545
00:50:57,740 --> 00:50:59,660
You maintain one infrastructure architecture.

1546
00:50:59,660 --> 00:51:02,460
You deploy it predictably to three different environments.

1547
00:51:02,460 --> 00:51:04,380
Changes flow through consistently.

1548
00:51:04,380 --> 00:51:07,180
And each environment gets exactly the level of resources

1549
00:51:07,180 --> 00:51:09,740
and controls appropriate to its risk profile.

1550
00:51:09,740 --> 00:51:11,260
That's not duplicate maintenance.

1551
00:51:11,260 --> 00:51:12,940
That's architectural discipline.

1552
00:51:12,940 --> 00:51:16,380
CICD integration, infrastructure as a delivery pipeline.

1553
00:51:16,380 --> 00:51:18,460
You've got bicep files sitting in Git.

1554
00:51:18,460 --> 00:51:20,700
You've got modules published to a registry.

1555
00:51:20,700 --> 00:51:22,380
You've got landing zone templates

1556
00:51:22,380 --> 00:51:24,620
that define what infrastructure should look like.

1557
00:51:24,620 --> 00:51:28,620
Now comes the part that turns all of this from intent into reality.

1558
00:51:28,620 --> 00:51:29,420
The pipeline.

1559
00:51:29,420 --> 00:51:32,140
The pipeline is where code becomes infrastructure.

1560
00:51:32,140 --> 00:51:33,100
But more than that,

1561
00:51:33,100 --> 00:51:36,220
it's where organizational discipline becomes automated enforcement.

1562
00:51:36,220 --> 00:51:39,580
Think about what needs to happen between someone writes a bicep file

1563
00:51:39,580 --> 00:51:42,300
and infrastructure actually exists in Azure.

1564
00:51:42,300 --> 00:51:43,740
The file needs to be validated.

1565
00:51:43,740 --> 00:51:44,620
Does it compile?

1566
00:51:44,620 --> 00:51:45,740
Are there syntax errors?

1567
00:51:45,740 --> 00:51:48,460
Do the parameter names match the variable definitions?

1568
00:51:48,460 --> 00:51:51,020
This catches obvious mistakes before they get deployed.

1569
00:51:51,020 --> 00:51:52,140
Then it needs to be built.

1570
00:51:52,140 --> 00:51:54,940
Bicep files get compiled into ARM templates.

1571
00:51:54,940 --> 00:51:57,740
That's the format Azure Resource Manager actually understands.

1572
00:51:57,740 --> 00:51:59,420
The build step produces artifacts,

1573
00:51:59,420 --> 00:52:02,540
the ARM template, parameter files, documentation,

1574
00:52:02,540 --> 00:52:04,140
everything needed for deployment.

1575
00:52:04,140 --> 00:52:05,340
Next comes testing.

1576
00:52:05,340 --> 00:52:08,300
You don't deploy to production without running the template somewhere first.

1577
00:52:08,300 --> 00:52:12,060
Test deployments verify that the template actually works in an Azure environment.

1578
00:52:12,060 --> 00:52:14,860
It will actually create the resources it claims to create.

1579
00:52:14,860 --> 00:52:17,180
The outputs will actually produce what's expected.

1580
00:52:17,180 --> 00:52:18,380
Policies will actually pass.

1581
00:52:18,380 --> 00:52:21,740
This all happens in a non-production subscription where mistakes don't matter.

1582
00:52:21,740 --> 00:52:23,900
Only after all of that comes actual deployment.

1583
00:52:23,900 --> 00:52:25,740
And deployment itself has gates.

1584
00:52:25,740 --> 00:52:28,620
Policy compliance checks validate that what you're about to deploy

1585
00:52:28,620 --> 00:52:30,540
aligns with organizational standards.

1586
00:52:30,540 --> 00:52:33,980
Security scanning looks for misconfigurations or security holes.

1587
00:52:33,980 --> 00:52:36,940
In non-production environments, these gates might be automated.

1588
00:52:36,940 --> 00:52:38,860
If it passes, it deploys immediately.

1589
00:52:38,860 --> 00:52:40,700
In production, there's an approval gate.

1590
00:52:40,700 --> 00:52:42,380
A human reviews what's about to happen.

1591
00:52:42,380 --> 00:52:43,740
They see the proposed changes.

1592
00:52:43,740 --> 00:52:45,180
They understand the blast radius.

1593
00:52:45,180 --> 00:52:46,540
They either approve or reject.

1594
00:52:46,540 --> 00:52:48,140
This enforces something crucial.

1595
00:52:48,140 --> 00:52:50,380
Code is truth, but humans still decide.

1596
00:52:50,380 --> 00:52:52,540
The pipeline stages themselves create the gates.

1597
00:52:52,540 --> 00:52:53,740
Validate stage runs.

1598
00:52:53,740 --> 00:52:55,660
If it fails, nothing moves forward.

1599
00:52:55,660 --> 00:52:59,180
Build stage runs, test stage runs, deploy to non-prod stage runs,

1600
00:52:59,180 --> 00:53:02,140
deploy to prod stage only runs if a human approves.

1601
00:53:02,140 --> 00:53:04,700
This progression ensures that mistakes don't cascade.

1602
00:53:04,700 --> 00:53:06,620
A syntax error gets caught in validation.

1603
00:53:06,620 --> 00:53:07,980
It doesn't reach production.

1604
00:53:07,980 --> 00:53:09,900
A policy violation gets caught in testing.

1605
00:53:09,900 --> 00:53:11,740
It doesn't break production compliance.

1606
00:53:11,740 --> 00:53:14,940
Authentication to Azure happens through the pipeline service connection.

1607
00:53:14,940 --> 00:53:17,420
This is where credentials matter operationally.

1608
00:53:17,420 --> 00:53:21,340
The pipeline needs to authenticate to Azure to actually deploy resources.

1609
00:53:21,340 --> 00:53:23,740
Traditionally, this meant storing credentials somewhere.

1610
00:53:23,740 --> 00:53:26,460
A service principles password, a client secret.

1611
00:53:26,460 --> 00:53:28,620
That introduces operational complexity.

1612
00:53:28,620 --> 00:53:29,580
Where do you store it?

1613
00:53:29,580 --> 00:53:30,540
How do you rotate it?

1614
00:53:30,540 --> 00:53:32,700
What happens if someone gets access to it?

1615
00:53:32,700 --> 00:53:35,660
Modern approaches use workload identity federation instead.

1616
00:53:35,660 --> 00:53:39,660
The pipeline runner, the compute identity of the CICD system itself,

1617
00:53:39,660 --> 00:53:43,340
is trusted by Azure through federated credential configuration.

1618
00:53:43,340 --> 00:53:45,100
The runner doesn't need to store credentials.

1619
00:53:45,100 --> 00:53:46,700
It just authenticates as itself.

1620
00:53:46,700 --> 00:53:47,500
Azure trusts it.

1621
00:53:47,500 --> 00:53:50,300
This eliminates an entire category of operational secrets.

1622
00:53:50,300 --> 00:53:54,060
Identity is a principle that seems obvious and gets violated constantly.

1623
00:53:54,060 --> 00:53:55,260
Run the pipeline twice.

1624
00:53:55,260 --> 00:53:56,940
You should get the same result both times.

1625
00:53:56,940 --> 00:54:00,540
The second run should update existing resources or do nothing if nothing changed.

1626
00:54:00,540 --> 00:54:02,060
It shouldn't create duplicates.

1627
00:54:02,060 --> 00:54:04,140
It shouldn't revert changes from the first run.

1628
00:54:04,140 --> 00:54:06,220
This matters because pipelines fail sometimes.

1629
00:54:06,220 --> 00:54:08,060
Networks, hiccup, timeouts happen.

1630
00:54:08,060 --> 00:54:09,340
You rerun the pipeline.

1631
00:54:09,340 --> 00:54:14,060
If it's not idempotent, the rerun might create a mess instead of cleaning up the first attempt.

1632
00:54:14,060 --> 00:54:17,020
The pipeline stages also define approval workflows.

1633
00:54:17,020 --> 00:54:18,940
Who can approve deployments to production?

1634
00:54:18,940 --> 00:54:22,620
In a small organization, maybe anyone with platform team membership.

1635
00:54:22,620 --> 00:54:27,020
In a large organization, maybe only the platform lead or a designated rotation of people.

1636
00:54:27,020 --> 00:54:30,140
In a regulated organization, maybe two people have to approve together.

1637
00:54:30,140 --> 00:54:31,740
The pipeline enforces this.

1638
00:54:31,740 --> 00:54:34,540
The gate won't open until the right approvals are in place.

1639
00:54:34,540 --> 00:54:36,380
This prevents unilateral production changes.

1640
00:54:36,380 --> 00:54:38,300
It's not human reviewers slowing things down.

1641
00:54:38,300 --> 00:54:41,180
It's human reviewers making sure someone is accountable.

1642
00:54:41,180 --> 00:54:43,740
The typical flow is validate, build, test, deploy.

1643
00:54:43,740 --> 00:54:45,980
Each stage validating and gating the next.

1644
00:54:45,980 --> 00:54:47,500
Validation catches errors.

1645
00:54:47,500 --> 00:54:48,940
Build creates artifacts.

1646
00:54:48,940 --> 00:54:50,380
Testing verifies behavior.

1647
00:54:50,380 --> 00:54:51,740
Deployment applies changes.

1648
00:54:51,740 --> 00:54:53,340
Each step removes uncertainty.

1649
00:54:53,340 --> 00:54:55,900
By the time resources actually get created in production,

1650
00:54:55,900 --> 00:55:00,620
the organization has already verified every aspect of them multiple times.

1651
00:55:00,620 --> 00:55:02,060
Mistakes haven't been eliminated.

1652
00:55:02,060 --> 00:55:03,580
Humans still make mistakes.

1653
00:55:03,580 --> 00:55:06,380
But the process catches the ones that can be caught automatically.

1654
00:55:06,380 --> 00:55:09,420
This is where infrastructure code stops being a file sitting in Git

1655
00:55:09,420 --> 00:55:11,180
and becomes a disciplined, repeatable,

1656
00:55:11,180 --> 00:55:12,380
auditable process.

1657
00:55:12,380 --> 00:55:13,580
Security by design.

1658
00:55:13,580 --> 00:55:14,860
Shift-left governance.

1659
00:55:14,860 --> 00:55:17,420
The pipeline you've built validates and gates deployment.

1660
00:55:17,420 --> 00:55:19,980
But those gates aren't just about catching syntax errors

1661
00:55:19,980 --> 00:55:21,980
or preventing accidental overrides.

1662
00:55:21,980 --> 00:55:25,580
They're about embedding security into the infrastructure definition itself.

1663
00:55:25,580 --> 00:55:26,780
This is Shift-left security.

1664
00:55:26,780 --> 00:55:29,500
The idea that you catch problems as early as possible

1665
00:55:29,500 --> 00:55:32,060
when the code is written, not when it's running.

1666
00:55:32,060 --> 00:55:33,980
Think about what happens in most organizations.

1667
00:55:33,980 --> 00:55:35,180
Infrastructure gets deployed.

1668
00:55:35,180 --> 00:55:36,060
It runs for a week.

1669
00:55:36,060 --> 00:55:37,820
Then security scanning happens.

1670
00:55:37,820 --> 00:55:41,260
Someone realizes there's a hard-coded password in a configuration file.

1671
00:55:41,260 --> 00:55:43,500
A storage account got created without encryption.

1672
00:55:43,500 --> 00:55:45,180
A role assignment is too broad.

1673
00:55:45,180 --> 00:55:47,420
Now you have to go back, fix it, redeploy it,

1674
00:55:47,420 --> 00:55:49,180
and hope it doesn't break anything in production.

1675
00:55:49,180 --> 00:55:49,980
This is backwards.

1676
00:55:49,980 --> 00:55:52,860
Security shouldn't be something you discover after things are running.

1677
00:55:52,860 --> 00:55:55,820
Shift-left flips this before a single resource gets created

1678
00:55:55,820 --> 00:55:58,620
before the template even compiles your running checks.

1679
00:55:58,620 --> 00:55:59,420
Linting rules.

1680
00:55:59,420 --> 00:56:01,900
Scan the bicep code and catch common mistakes.

1681
00:56:01,900 --> 00:56:03,340
Hard-coded secrets.

1682
00:56:03,340 --> 00:56:06,780
Missing tags when your organization requires tags on everything.

1683
00:56:06,780 --> 00:56:08,860
Overly permissive access controls.

1684
00:56:08,860 --> 00:56:11,420
Resource names that don't follow your naming convention.

1685
00:56:11,420 --> 00:56:13,260
These rules catch problems at the source.

1686
00:56:13,260 --> 00:56:14,460
Someone writes a line of code.

1687
00:56:14,460 --> 00:56:16,060
The Linter flags it immediately.

1688
00:56:16,060 --> 00:56:18,220
They fix it before it ever gets committed to Git.

1689
00:56:18,220 --> 00:56:20,060
Policy compliance checks happen next.

1690
00:56:20,060 --> 00:56:23,260
Your organization has policies defined in Azure Policy.

1691
00:56:23,260 --> 00:56:25,580
Before you deploy to production, you want to know,

1692
00:56:25,580 --> 00:56:27,580
would this template pass those policies?

1693
00:56:27,580 --> 00:56:30,140
What if deployments actually instantiate the template

1694
00:56:30,140 --> 00:56:33,180
in a test environment and run it through your policy engine?

1695
00:56:33,180 --> 00:56:35,580
If the template creates a storage account without encryption,

1696
00:56:35,580 --> 00:56:36,860
the policy flags it.

1697
00:56:36,860 --> 00:56:39,500
If it tries to open ports that your organization forbids,

1698
00:56:39,500 --> 00:56:40,620
the policy flags it.

1699
00:56:40,620 --> 00:56:42,540
You find out before production, not after.

1700
00:56:42,540 --> 00:56:45,100
The cycle time for fixing is minutes, not hours or days.

1701
00:56:45,100 --> 00:56:46,860
This all happens in the pipeline.

1702
00:56:46,860 --> 00:56:48,460
Long before human approval.

1703
00:56:48,460 --> 00:56:50,860
Automated checks create the first line of defense.

1704
00:56:50,860 --> 00:56:53,660
By the time someone is reviewing a deployment for approval,

1705
00:56:53,660 --> 00:56:55,580
they're not reviewing a blind template.

1706
00:56:55,580 --> 00:56:57,260
They're reviewing something that's already passed

1707
00:56:57,260 --> 00:56:58,860
multiple automated checks.

1708
00:56:58,860 --> 00:57:00,860
The approval becomes a gate for judgment calls,

1709
00:57:00,860 --> 00:57:02,780
not a safety net for obvious mistakes.

1710
00:57:02,780 --> 00:57:04,780
Secrets management is where shift left security

1711
00:57:04,780 --> 00:57:06,380
becomes operational discipline.

1712
00:57:06,380 --> 00:57:07,980
Bicep files go into Git.

1713
00:57:07,980 --> 00:57:11,020
Git repositories are readable by team members who need to review code,

1714
00:57:11,020 --> 00:57:12,700
but secrets can't live in Git.

1715
00:57:12,700 --> 00:57:15,740
Never, not in parameter files, not in bicep variables,

1716
00:57:15,740 --> 00:57:16,620
not anywhere.

1717
00:57:16,620 --> 00:57:18,940
Linting catches hard coded secrets immediately.

1718
00:57:18,940 --> 00:57:21,580
If someone tries to paste a password into a bicep file,

1719
00:57:21,580 --> 00:57:22,700
the linter flags it.

1720
00:57:22,700 --> 00:57:24,700
It won't let the file even compile.

1721
00:57:24,700 --> 00:57:26,460
This forces the conversation.

1722
00:57:26,460 --> 00:57:28,540
How do secrets actually get into production?

1723
00:57:28,540 --> 00:57:30,860
The answer is Key Vault or Pipeline Secret stores.

1724
00:57:30,860 --> 00:57:32,860
The Pipeline injects secrets at deployment time.

1725
00:57:32,860 --> 00:57:34,940
The bicep file doesn't know what the password is.

1726
00:57:34,940 --> 00:57:36,380
It just knows there's a secret it needs.

1727
00:57:36,380 --> 00:57:39,180
The pipeline retrieves the secret from Key Vault during deployment

1728
00:57:39,180 --> 00:57:40,220
and passes it in.

1729
00:57:40,220 --> 00:57:41,740
The secret never sits in code.

1730
00:57:41,740 --> 00:57:43,180
It never gets checked into Git.

1731
00:57:43,180 --> 00:57:44,860
It never lives anywhere it shouldn't.

1732
00:57:44,860 --> 00:57:47,740
Managed identities represent the modern approach to this problem.

1733
00:57:47,740 --> 00:57:49,980
If a resource needs to authenticate to another service,

1734
00:57:49,980 --> 00:57:51,100
it doesn't need a password.

1735
00:57:51,100 --> 00:57:52,620
It can use its managed identity.

1736
00:57:52,620 --> 00:57:54,780
Azure issues it a credential automatically.

1737
00:57:54,780 --> 00:57:56,940
There's nothing to store, nothing to rotate,

1738
00:57:56,940 --> 00:57:57,900
nothing to leak.

1739
00:57:57,900 --> 00:58:00,380
This is simpler and more secure than the alternative.

1740
00:58:00,380 --> 00:58:01,980
Auditability is the final piece.

1741
00:58:01,980 --> 00:58:03,740
Every deployment should leave a trace.

1742
00:58:03,740 --> 00:58:06,380
Who deployed what, when, and why should be recoverable?

1743
00:58:06,380 --> 00:58:07,900
Git history shows what changed.

1744
00:58:07,900 --> 00:58:10,140
Pipeline logs show what ran and what the output was.

1745
00:58:10,140 --> 00:58:13,020
Azure audit logs show what resources were created

1746
00:58:13,020 --> 00:58:14,300
and by which identity.

1747
00:58:14,300 --> 00:58:17,260
If something goes wrong, you can trace back through all of these layers

1748
00:58:17,260 --> 00:58:19,900
and understand exactly what happened and who did it.

1749
00:58:19,900 --> 00:58:23,820
Security being embedded in every stage means it's not a separate concern.

1750
00:58:23,820 --> 00:58:25,020
It's not something bolt on.

1751
00:58:25,020 --> 00:58:26,140
It's architectural.

1752
00:58:26,140 --> 00:58:27,500
From the moment code is written,

1753
00:58:27,500 --> 00:58:29,500
until resources are running in production,

1754
00:58:29,500 --> 00:58:31,500
security is being checked continuously.

1755
00:58:31,500 --> 00:58:32,860
Problems get caught early.

1756
00:58:32,860 --> 00:58:35,260
Secrets stay protected, access stays controlled.

1757
00:58:35,260 --> 00:58:36,780
Auditability is automatic.

1758
00:58:36,780 --> 00:58:38,380
That's shift left security.

1759
00:58:38,380 --> 00:58:40,700
That's where architecture meets operational reality.

1760
00:58:40,700 --> 00:58:43,100
Bicep versus Terraform.

1761
00:58:43,100 --> 00:58:44,540
The strategic choice.

1762
00:58:44,540 --> 00:58:47,500
At some point, someone on your architecture team will ask the question,

1763
00:58:47,500 --> 00:58:49,500
should we be using bicep or Terraform?

1764
00:58:49,500 --> 00:58:51,260
The question usually carries weight,

1765
00:58:51,260 --> 00:58:52,940
like you're supposed to declare a winner.

1766
00:58:52,940 --> 00:58:54,220
Pick a side, commit.

1767
00:58:54,220 --> 00:58:56,620
The reality is messier and more interesting than that.

1768
00:58:56,620 --> 00:58:57,980
Both are valid approaches.

1769
00:58:57,980 --> 00:59:00,380
The choice depends entirely on what you're building,

1770
00:59:00,380 --> 00:59:02,460
not on which tool is technically superior.

1771
00:59:02,460 --> 00:59:04,380
This matters because it's a foundational decision.

1772
00:59:04,380 --> 00:59:06,140
It shapes how your team thinks,

1773
00:59:06,140 --> 00:59:07,580
how your pipelines are structured,

1774
00:59:07,580 --> 00:59:09,260
how your modules are organized,

1775
00:59:09,260 --> 00:59:11,500
what you'll struggle with, and what you'll take for granted.

1776
00:59:11,500 --> 00:59:12,700
Bicep is Azure Native.

1777
00:59:12,700 --> 00:59:14,620
It moves at the speed of Azure itself.

1778
00:59:14,620 --> 00:59:16,460
When Microsoft releases a new service,

1779
00:59:16,460 --> 00:59:17,980
copilot in your infrastructure,

1780
00:59:17,980 --> 00:59:20,540
new compliance controls, novel security features,

1781
00:59:20,540 --> 00:59:21,980
bicep supports it immediately,

1782
00:59:21,980 --> 00:59:22,780
not eventually,

1783
00:59:22,780 --> 00:59:24,780
not in the next provider update cycle.

1784
00:59:24,780 --> 00:59:27,980
Immediately, the language compiles directly to arm templates.

1785
00:59:27,980 --> 00:59:29,180
There's no translation layer,

1786
00:59:29,180 --> 00:59:32,140
no abstraction that might lag behind Azure's evolution.

1787
00:59:32,140 --> 00:59:33,420
This is enormously valuable

1788
00:59:33,420 --> 00:59:35,340
if your organization is primarily on Azure

1789
00:59:35,340 --> 00:59:38,060
and you need to stay current with whatever Microsoft ships.

1790
00:59:38,060 --> 00:59:39,260
There's no separate state file.

1791
00:59:39,260 --> 00:59:40,380
This sounds like a limitation

1792
00:59:40,380 --> 00:59:42,140
until you experience the operational weight

1793
00:59:42,140 --> 00:59:43,820
of managing state files.

1794
00:59:43,820 --> 00:59:45,980
Terraform maintains an explicit state file

1795
00:59:45,980 --> 00:59:47,500
that tracks what it's managing.

1796
00:59:47,500 --> 00:59:49,100
This state file is truth.

1797
00:59:49,100 --> 00:59:51,100
It tells Terraform what resources exist,

1798
00:59:51,100 --> 00:59:52,460
what properties they have,

1799
00:59:52,460 --> 00:59:54,780
what the current versus desired state looks like.

1800
00:59:54,780 --> 00:59:55,580
This is powerful.

1801
00:59:55,580 --> 00:59:58,460
It enables detailed planning and drift detection.

1802
00:59:58,460 --> 01:00:00,220
It's also operationally complex.

1803
01:00:00,220 --> 01:00:01,340
Where does the state file live?

1804
01:00:01,340 --> 01:00:02,300
Who has access to it?

1805
01:00:02,300 --> 01:00:03,180
How do you back it up?

1806
01:00:03,180 --> 01:00:04,460
What happens if it gets corrupted?

1807
01:00:04,460 --> 01:00:06,220
What happens if two people deploy simultaneously

1808
01:00:06,220 --> 01:00:08,620
and the state file gets into an inconsistent state?

1809
01:00:08,620 --> 01:00:10,220
By-sepside steps all of this.

1810
01:00:10,220 --> 01:00:12,460
Azure Resource Manager is the source of truth.

1811
01:00:12,460 --> 01:00:13,420
You deploy a template.

1812
01:00:13,420 --> 01:00:14,780
Arm applies the changes.

1813
01:00:14,780 --> 01:00:17,260
The actual resource state in Azure is what matters.

1814
01:00:17,260 --> 01:00:18,380
Terraform is multi-cloud.

1815
01:00:18,380 --> 01:00:19,260
This changes everything

1816
01:00:19,260 --> 01:00:21,500
if you're managing infrastructure across AWS,

1817
01:00:21,500 --> 01:00:24,460
GCP, Azure, and on-premises simultaneously.

1818
01:00:24,460 --> 01:00:25,980
With Terraform, you write one workflow

1819
01:00:25,980 --> 01:00:27,580
that spans all your clouds.

1820
01:00:27,580 --> 01:00:29,820
One CICD model, one language,

1821
01:00:29,820 --> 01:00:31,900
one way of thinking about infrastructure.

1822
01:00:31,900 --> 01:00:33,580
The Terraform registry contains modules

1823
01:00:33,580 --> 01:00:35,580
for virtually every platform in service.

1824
01:00:35,580 --> 01:00:39,500
AWS modules, GCP modules, Kubernetes modules, data dog modules.

1825
01:00:39,500 --> 01:00:42,540
If it has an API, someone's written a Terraform module for it,

1826
01:00:42,540 --> 01:00:44,940
this is the lingua franca of infrastructure teams

1827
01:00:44,940 --> 01:00:46,860
managing anything beyond a single cloud.

1828
01:00:46,860 --> 01:00:48,860
The trade-off is that Azure specific features

1829
01:00:48,860 --> 01:00:51,500
sometimes arrive later in Terraform than in BICEP.

1830
01:00:51,500 --> 01:00:54,220
The Azure provider needs to be updated by the maintainers.

1831
01:00:54,220 --> 01:00:55,180
It happens quickly.

1832
01:00:55,180 --> 01:00:56,700
Usually days, not months,

1833
01:00:56,700 --> 01:00:58,140
but there's still a lag.

1834
01:00:58,140 --> 01:01:01,180
For cutting edge Azure features, BICEP gets their first.

1835
01:01:01,180 --> 01:01:03,260
State management in Terraform is both a strength

1836
01:01:03,260 --> 01:01:04,700
and an operational burden.

1837
01:01:04,700 --> 01:01:07,020
The state file enables powerful drift detection.

1838
01:01:07,020 --> 01:01:10,300
Terraform can compare what it expects versus what actually exists

1839
01:01:10,300 --> 01:01:12,140
in Azure and tell you exactly what change.

1840
01:01:12,140 --> 01:01:14,700
It can target specific resources for updates.

1841
01:01:14,700 --> 01:01:17,420
It can perform sophisticated dependency ordering.

1842
01:01:17,420 --> 01:01:19,660
These capabilities come from that state file,

1843
01:01:19,660 --> 01:01:22,220
but they come with the requirement that you manage it carefully.

1844
01:01:22,220 --> 01:01:24,860
Production state files need to be protected, encrypted,

1845
01:01:24,860 --> 01:01:26,460
backed up, and audited.

1846
01:01:26,460 --> 01:01:28,620
This isn't something you bolt on casually.

1847
01:01:28,620 --> 01:01:30,060
It's a design decision that ripples

1848
01:01:30,060 --> 01:01:31,980
through your infrastructure practices.

1849
01:01:31,980 --> 01:01:35,260
Here's where Azure verified modules matter to this conversation.

1850
01:01:35,260 --> 01:01:37,740
AVM exists in both BICEP and Terraform.

1851
01:01:37,740 --> 01:01:40,700
It's the same architectural thinking implemented in both languages.

1852
01:01:40,700 --> 01:01:42,460
This means your organizational standards

1853
01:01:42,460 --> 01:01:43,980
don't have to choose a language.

1854
01:01:43,980 --> 01:01:46,780
You can standardize on architectural principles.

1855
01:01:46,780 --> 01:01:48,540
How networks should be configured,

1856
01:01:48,540 --> 01:01:50,140
how identity should integrate,

1857
01:01:50,140 --> 01:01:52,140
what compliance baselines should look like,

1858
01:01:52,140 --> 01:01:55,660
and then implement those in whatever language your team prefers.

1859
01:01:55,660 --> 01:01:57,500
The decision ultimately comes down to scope.

1860
01:01:57,500 --> 01:01:59,340
Are you building Azure infrastructure?

1861
01:01:59,340 --> 01:02:00,620
Is Azure your cloud?

1862
01:02:00,620 --> 01:02:02,380
Then BICEP is probably the right choice.

1863
01:02:02,380 --> 01:02:04,700
It's native, it's current, it's simple operationally.

1864
01:02:04,700 --> 01:02:06,380
Are you managing multiple clouds?

1865
01:02:06,380 --> 01:02:08,780
Is Azure one piece of a larger infrastructure puzzle?

1866
01:02:08,780 --> 01:02:09,980
Then Terraform is probably right.

1867
01:02:09,980 --> 01:02:12,300
You get a single tool, a single workflow,

1868
01:02:12,300 --> 01:02:15,180
a single way of thinking that spans your entire infrastructure

1869
01:02:15,180 --> 01:02:15,820
estate.

1870
01:02:15,820 --> 01:02:17,900
The architectural principles we've covered,

1871
01:02:17,900 --> 01:02:19,580
modules, governance, scopes,

1872
01:02:19,580 --> 01:02:22,140
lifecycle management, all apply to both.

1873
01:02:22,140 --> 01:02:24,220
The differences are in implementation details.

1874
01:02:24,220 --> 01:02:25,580
The outcome should be the same.

1875
01:02:25,580 --> 01:02:27,900
Infrastructure that's governed, reproducible,

1876
01:02:27,900 --> 01:02:30,060
auditable, and manageable at scale.

1877
01:02:30,060 --> 01:02:31,740
Pick based on your actual situation,

1878
01:02:31,740 --> 01:02:34,780
not based on which tools sounds better in a conversation.

1879
01:02:34,780 --> 01:02:38,140
Governance at scale, multiple teams, multiple stacks.

1880
01:02:38,140 --> 01:02:40,940
The architecture we've built so far works beautifully in theory,

1881
01:02:40,940 --> 01:02:43,180
one landing zone template, one set of modules,

1882
01:02:43,180 --> 01:02:44,380
one governance model.

1883
01:02:44,380 --> 01:02:46,860
But theory meets reality when you're not deploying infrastructure

1884
01:02:46,860 --> 01:02:49,660
for a single workload, you're deploying for dozens of teams,

1885
01:02:49,660 --> 01:02:51,180
hundreds of subscriptions,

1886
01:02:51,180 --> 01:02:53,740
thousands of resources spread across environments

1887
01:02:53,740 --> 01:02:55,820
that barely communicate with each other.

1888
01:02:55,820 --> 01:02:58,300
Governance doesn't collapse just because scale increases,

1889
01:02:58,300 --> 01:03:01,500
it has to evolve. Enterprise environments force a different question.

1890
01:03:01,500 --> 01:03:04,300
Not how do we govern our infrastructure, but a car?

1891
01:03:04,300 --> 01:03:07,900
But how do we govern while letting teams move independently?

1892
01:03:07,900 --> 01:03:09,260
The answer is boundaries.

1893
01:03:09,260 --> 01:03:11,260
The clearest boundary is ownership.

1894
01:03:11,260 --> 01:03:12,620
A platform team exists.

1895
01:03:12,620 --> 01:03:14,300
Their job is building the foundation.

1896
01:03:14,300 --> 01:03:15,900
They own the management group hierarchy,

1897
01:03:15,900 --> 01:03:17,500
they own the shared infrastructure,

1898
01:03:17,500 --> 01:03:19,260
the hub network, the directory integration,

1899
01:03:19,260 --> 01:03:20,060
the central logging.

1900
01:03:20,060 --> 01:03:23,180
They own the policies that apply across the entire organization.

1901
01:03:23,180 --> 01:03:24,140
They publish modules,

1902
01:03:24,140 --> 01:03:25,580
they maintain the module registry,

1903
01:03:25,580 --> 01:03:26,620
they set standards.

1904
01:03:26,620 --> 01:03:28,540
Application teams exist separately.

1905
01:03:28,540 --> 01:03:29,900
Their job is building products,

1906
01:03:29,900 --> 01:03:31,340
they own specific subscriptions,

1907
01:03:31,340 --> 01:03:33,340
they own the resources, their application needs,

1908
01:03:33,340 --> 01:03:35,660
they don't own the shared layer, they consume it.

1909
01:03:35,660 --> 01:03:38,540
This separation prevents two things from happening simultaneously.

1910
01:03:38,540 --> 01:03:41,340
Application teams can't break shared infrastructure by accident,

1911
01:03:41,340 --> 01:03:42,860
they can't modify the networking layer

1912
01:03:42,860 --> 01:03:44,860
and accidentally cut off connectivity for everyone.

1913
01:03:44,860 --> 01:03:47,820
They can't change our back in a way that locks out the security team,

1914
01:03:47,820 --> 01:03:50,060
but also the platform team doesn't become a bottleneck.

1915
01:03:50,060 --> 01:03:53,500
Application teams have autonomy within their own subscription boundaries.

1916
01:03:53,500 --> 01:03:54,940
They can deploy resources,

1917
01:03:54,940 --> 01:03:56,460
they can configure their application.

1918
01:03:56,460 --> 01:03:58,860
They can iterate quickly the multiple stacks pattern,

1919
01:03:58,860 --> 01:04:00,220
reinforces this boundary.

1920
01:04:00,220 --> 01:04:02,220
The platform team manages several stacks,

1921
01:04:02,220 --> 01:04:03,340
one for connectivity,

1922
01:04:03,340 --> 01:04:04,300
the hub network,

1923
01:04:04,300 --> 01:04:07,580
the routing, the integration with on-premises or cloud providers.

1924
01:04:07,580 --> 01:04:09,580
One for identity, service principles,

1925
01:04:09,580 --> 01:04:12,380
managed identities, role assignments at the tenant level,

1926
01:04:12,380 --> 01:04:14,620
one for shared services, log aggregation,

1927
01:04:14,620 --> 01:04:17,260
backup infrastructure, disaster recovery.

1928
01:04:17,260 --> 01:04:18,780
Each stack has its own life cycle,

1929
01:04:18,780 --> 01:04:20,460
each has its own approval process,

1930
01:04:20,460 --> 01:04:21,900
each is versioned separately.

1931
01:04:21,900 --> 01:04:23,900
Application teams deploy their own stacks

1932
01:04:23,900 --> 01:04:26,060
within the subscriptions they've been allocated.

1933
01:04:26,060 --> 01:04:29,020
Their stack creates the resources specific to their application.

1934
01:04:29,020 --> 01:04:32,380
Virtual machines, databases, storage, APIs,

1935
01:04:32,380 --> 01:04:36,620
but these stacks operate within the governance boundaries set by the platform stacks.

1936
01:04:36,620 --> 01:04:40,220
The networking stack has already created the virtual networks and subnets.

1937
01:04:40,220 --> 01:04:42,540
The application stack deploys into those networks.

1938
01:04:42,540 --> 01:04:45,580
The identity stack has already configured role assignments.

1939
01:04:45,580 --> 01:04:47,980
The application stack uses those identities.

1940
01:04:47,980 --> 01:04:50,140
The application team isn't reinventing the wheel,

1941
01:04:50,140 --> 01:04:51,740
they're working within a framework.

1942
01:04:51,740 --> 01:04:53,260
Deny settings on platform stacks

1943
01:04:53,260 --> 01:04:55,020
enforce this boundary technically.

1944
01:04:55,020 --> 01:04:58,220
The platform team sets deny-write and delete on the networking stack.

1945
01:04:58,220 --> 01:05:00,860
Application teams can read the network configuration.

1946
01:05:00,860 --> 01:05:02,620
They can deploy into the networks,

1947
01:05:02,620 --> 01:05:04,700
but they can't modify the networks themselves,

1948
01:05:04,700 --> 01:05:06,060
they can't change routes,

1949
01:05:06,060 --> 01:05:09,340
they can't alter security groups in ways that would affect other applications.

1950
01:05:09,340 --> 01:05:11,180
The deny setting makes the boundary hard.

1951
01:05:11,180 --> 01:05:13,420
It's not a suggestion, it's a technical control.

1952
01:05:13,420 --> 01:05:15,660
The governance model needs to be explicit.

1953
01:05:15,660 --> 01:05:17,580
Teams need a document, or better,

1954
01:05:17,580 --> 01:05:19,900
a living reference in your documentation system

1955
01:05:19,900 --> 01:05:21,180
that answers three questions.

1956
01:05:21,180 --> 01:05:23,100
What's shared the hub network, the directory,

1957
01:05:23,100 --> 01:05:25,100
the log storage, the backup infrastructure,

1958
01:05:25,100 --> 01:05:27,340
teams know this is owned by the platform team.

1959
01:05:27,340 --> 01:05:29,020
Changes require platform team approval,

1960
01:05:29,020 --> 01:05:29,900
but what's delegated?

1961
01:05:29,900 --> 01:05:31,900
Application teams control their subscriptions.

1962
01:05:31,900 --> 01:05:33,100
They can create resources,

1963
01:05:33,100 --> 01:05:36,140
they can modify application-specific configuration,

1964
01:05:36,140 --> 01:05:39,020
they can iterate what's forbidden, certain resource types,

1965
01:05:39,020 --> 01:05:42,620
certain configurations, things that would violate policy or compliance.

1966
01:05:42,620 --> 01:05:44,220
Teams know these are off-limits.

1967
01:05:44,220 --> 01:05:45,500
The policies prevent them.

1968
01:05:45,500 --> 01:05:47,260
The documentation explains why.

1969
01:05:47,260 --> 01:05:49,660
This model scales because it's self-explanatory.

1970
01:05:49,660 --> 01:05:51,500
New teams onboard into a landing zone.

1971
01:05:51,500 --> 01:05:52,780
They read the documentation.

1972
01:05:52,780 --> 01:05:54,140
They understand the boundaries.

1973
01:05:54,140 --> 01:05:56,620
They understand what they own and what they don't.

1974
01:05:56,620 --> 01:05:59,260
They understand what they can do and what requires escalation.

1975
01:05:59,260 --> 01:06:01,820
The platform team doesn't need to brief every team individually.

1976
01:06:01,820 --> 01:06:03,820
The model is codified, it's reproducible.

1977
01:06:03,820 --> 01:06:05,340
It's in the infrastructure itself.

1978
01:06:05,340 --> 01:06:07,020
Governance at enterprise scale works

1979
01:06:07,020 --> 01:06:08,780
because it's not trying to control everything.

1980
01:06:08,780 --> 01:06:11,420
It's controlling what matters and delegating the rest.

1981
01:06:11,420 --> 01:06:14,140
Drift, compliance, and continuous validation.

1982
01:06:14,140 --> 01:06:16,540
You've got your infrastructure defined in Bicep.

1983
01:06:16,540 --> 01:06:18,220
You've got it deployed through a pipeline.

1984
01:06:18,220 --> 01:06:20,460
You've got governance enforced at multiple levels.

1985
01:06:20,460 --> 01:06:21,980
And then reality happens.

1986
01:06:21,980 --> 01:06:24,220
Someone logs into the portal at 2am on a Sunday

1987
01:06:24,220 --> 01:06:25,740
to troubleshoot a performance issue.

1988
01:06:25,740 --> 01:06:26,700
They make a change.

1989
01:06:26,700 --> 01:06:28,780
Just a quick SQ upgrade on a database.

1990
01:06:28,780 --> 01:06:30,540
They plan to document it on Monday.

1991
01:06:30,540 --> 01:06:31,900
They never get around to it.

1992
01:06:31,900 --> 01:06:33,260
Now your template says one thing.

1993
01:06:33,260 --> 01:06:35,260
Your actual infrastructure says another.

1994
01:06:35,260 --> 01:06:36,620
That gap is drift.

1995
01:06:36,620 --> 01:06:37,980
And if you're not watching for it,

1996
01:06:37,980 --> 01:06:39,260
you'll never know it's there.

1997
01:06:39,260 --> 01:06:42,140
Drift is the quiet failure mode of infrastructure as code.

1998
01:06:42,140 --> 01:06:43,420
The template isn't wrong.

1999
01:06:43,420 --> 01:06:44,940
The infrastructure isn't broken,

2000
01:06:44,940 --> 01:06:46,620
but they're no longer synchronized.

2001
01:06:46,620 --> 01:06:48,060
Over time, drift compounds,

2002
01:06:48,060 --> 01:06:50,540
one change becomes two, two becomes five.

2003
01:06:50,540 --> 01:06:52,780
Eventually, your infrastructure has evolved so far

2004
01:06:52,780 --> 01:06:54,380
from your template that nobody's quite sure

2005
01:06:54,380 --> 01:06:56,380
what the actual topology looks like.

2006
01:06:56,380 --> 01:06:57,900
Deploying again becomes risky.

2007
01:06:57,900 --> 01:06:59,900
You might override changes you didn't know about.

2008
01:06:59,900 --> 01:07:01,020
You might break something.

2009
01:07:01,020 --> 01:07:02,940
Deployment stacks address part of this.

2010
01:07:02,940 --> 01:07:05,580
A stack tracks which resources it manages.

2011
01:07:05,580 --> 01:07:06,700
When you run a deployment,

2012
01:07:06,700 --> 01:07:09,820
the stack knows exactly which resources are supposed to be there.

2013
01:07:09,820 --> 01:07:12,700
If a resource has been manually deleted, the stack detects it.

2014
01:07:12,700 --> 01:07:14,300
If a resource has been manually created

2015
01:07:14,300 --> 01:07:15,660
that wasn't in the template,

2016
01:07:15,660 --> 01:07:17,500
the stack sees it's unmanaged.

2017
01:07:17,500 --> 01:07:18,620
But here's the limitation.

2018
01:07:18,620 --> 01:07:20,620
The stack can't automatically decide what to do

2019
01:07:20,620 --> 01:07:22,060
about unmanaged resources.

2020
01:07:22,060 --> 01:07:22,860
It can track them.

2021
01:07:22,860 --> 01:07:23,740
It can report them.

2022
01:07:23,740 --> 01:07:26,060
It can't fix them without explicit configuration.

2023
01:07:26,060 --> 01:07:28,860
Azure Policy is the complementary piece.

2024
01:07:28,860 --> 01:07:31,900
Policies define what compliant infrastructure looks like.

2025
01:07:31,900 --> 01:07:33,100
A policy might say,

2026
01:07:33,100 --> 01:07:35,580
all storage accounts must have encryption enabled.

2027
01:07:35,580 --> 01:07:37,820
All networks must have network security groups.

2028
01:07:37,820 --> 01:07:40,300
All applications must have monitoring configured.

2029
01:07:40,300 --> 01:07:41,500
When you violate a policy,

2030
01:07:41,500 --> 01:07:42,620
it doesn't prevent the action,

2031
01:07:42,620 --> 01:07:44,380
unless you've set the effect to deny.

2032
01:07:44,380 --> 01:07:46,540
But it does flag the resource as non-compliant.

2033
01:07:46,540 --> 01:07:48,300
That flag appears in compliance reports.

2034
01:07:48,300 --> 01:07:49,420
You know something's wrong.

2035
01:07:49,420 --> 01:07:51,500
The discipline comes from continuous validation.

2036
01:07:51,500 --> 01:07:54,220
What if deployments aren't just for before deployment previews?

2037
01:07:54,220 --> 01:07:55,660
They're continuous monitoring tools.

2038
01:07:55,660 --> 01:07:57,180
Run what if regularly?

2039
01:07:57,180 --> 01:07:58,060
Every day.

2040
01:07:58,060 --> 01:07:58,860
Every week.

2041
01:07:58,860 --> 01:08:01,740
Compare what your template says should be there with what actually is.

2042
01:08:01,740 --> 01:08:03,100
The difference is drift.

2043
01:08:03,100 --> 01:08:04,940
When you see drift, you have a choice.

2044
01:08:04,940 --> 01:08:07,580
Redploy the template to bring reality back in line

2045
01:08:07,580 --> 01:08:09,740
or update the template to match reality.

2046
01:08:09,740 --> 01:08:11,820
Either way, you're making a conscious decision.

2047
01:08:11,820 --> 01:08:14,220
You're not allowing drift to accumulate silently.

2048
01:08:14,220 --> 01:08:16,060
Compliance monitoring should be the same.

2049
01:08:16,060 --> 01:08:17,020
Not a quarterly audit.

2050
01:08:17,020 --> 01:08:18,860
Not a security review once a year.

2051
01:08:18,860 --> 01:08:19,820
Continuous.

2052
01:08:19,820 --> 01:08:22,700
Dashboards that show policy compliance in real time.

2053
01:08:22,700 --> 01:08:24,060
Which resources are compliant,

2054
01:08:24,060 --> 01:08:25,740
which are flagged as non-compliant,

2055
01:08:25,740 --> 01:08:27,100
which policies have exceptions.

2056
01:08:27,100 --> 01:08:29,420
How many resources are managed versus unmanaged?

2057
01:08:29,420 --> 01:08:31,340
These dashboards need to be visible,

2058
01:08:31,340 --> 01:08:33,900
not hidden in a compliance portal that nobody checks.

2059
01:08:33,900 --> 01:08:35,580
They should be in your operations center

2060
01:08:35,580 --> 01:08:36,860
on your team's dashboards,

2061
01:08:36,860 --> 01:08:38,060
where people see them every day.

2062
01:08:38,060 --> 01:08:40,700
The principle is straightforward but often violated.

2063
01:08:40,700 --> 01:08:42,780
Infrastructure should match the template.

2064
01:08:42,780 --> 01:08:43,820
When it doesn't,

2065
01:08:43,820 --> 01:08:45,980
that's not normal operational variance.

2066
01:08:45,980 --> 01:08:46,780
That's a problem.

2067
01:08:46,780 --> 01:08:48,860
The problem might be that someone made a change they shouldn't have

2068
01:08:48,860 --> 01:08:51,180
and now you need to investigate and understand why.

2069
01:08:51,180 --> 01:08:53,580
The problem might be that the template is out of date

2070
01:08:53,580 --> 01:08:54,540
and needs updating.

2071
01:08:54,540 --> 01:08:56,780
The problem might be that the policy is too strict

2072
01:08:56,780 --> 01:08:57,980
and needs adjustment.

2073
01:08:57,980 --> 01:08:59,500
Whatever the problem is, it needs attention.

2074
01:08:59,500 --> 01:09:01,900
This is the difference between treating your infrastructure code

2075
01:09:01,900 --> 01:09:03,020
as documentation

2076
01:09:03,020 --> 01:09:04,060
and treating it as truth.

2077
01:09:04,060 --> 01:09:06,540
Documentation describes what you think exists.

2078
01:09:06,540 --> 01:09:08,060
Truth is what actually does.

2079
01:09:08,060 --> 01:09:10,300
The infrastructure as code approach only works

2080
01:09:10,300 --> 01:09:12,460
if you're committed to keeping them synchronized.

2081
01:09:12,460 --> 01:09:14,220
That synchronization is continuous work.

2082
01:09:14,220 --> 01:09:15,340
It's drift detection.

2083
01:09:15,340 --> 01:09:16,860
It's compliance monitoring.

2084
01:09:16,860 --> 01:09:18,620
It's validation running regularly.

2085
01:09:18,620 --> 01:09:20,620
It's not something you do once and move on.

2086
01:09:20,620 --> 01:09:22,380
Compliance isn't a checkpoint you pass.

2087
01:09:22,380 --> 01:09:23,500
It's an ongoing practice.

2088
01:09:23,500 --> 01:09:26,380
Migrations and brownfield scenarios.

2089
01:09:26,380 --> 01:09:28,540
Most organizations don't start with bicep.

2090
01:09:28,540 --> 01:09:29,980
You inherit a reality.

2091
01:09:29,980 --> 01:09:32,780
Someone deployed resources through the portal three years ago.

2092
01:09:32,780 --> 01:09:34,220
Another team wrote arm templates

2093
01:09:34,220 --> 01:09:35,900
that nobody fully understands anymore.

2094
01:09:35,900 --> 01:09:37,420
A third team uses Terraform.

2095
01:09:37,420 --> 01:09:39,180
You've got Azure resource graph queries

2096
01:09:39,180 --> 01:09:42,060
that reveal often resources nobody remembers creating.

2097
01:09:42,060 --> 01:09:43,660
You've got virtual networks

2098
01:09:43,660 --> 01:09:46,060
configured through scripts that live on someone's laptop.

2099
01:09:46,060 --> 01:09:47,020
But you've got a brownfield.

2100
01:09:47,020 --> 01:09:50,060
The question isn't how to build perfect infrastructure from scratch.

2101
01:09:50,060 --> 01:09:51,900
It's how to gradually transform what exists

2102
01:09:51,900 --> 01:09:53,900
into something governed and maintainable.

2103
01:09:53,900 --> 01:09:55,260
The migration isn't a cut over.

2104
01:09:55,260 --> 01:09:56,060
This is critical.

2105
01:09:56,060 --> 01:09:57,100
You don't wake up one morning

2106
01:09:57,100 --> 01:09:59,660
and decide everything converts to bicep by Friday.

2107
01:09:59,660 --> 01:10:01,020
That's how you break production.

2108
01:10:01,020 --> 01:10:02,220
Migration is a journey.

2109
01:10:02,220 --> 01:10:03,180
It happens incrementally.

2110
01:10:03,180 --> 01:10:04,460
It happens in stages.

2111
01:10:04,460 --> 01:10:05,900
Some workloads move first.

2112
01:10:05,900 --> 01:10:07,820
Others follow on their own timeline.

2113
01:10:07,820 --> 01:10:09,980
The typical pattern starts with new resources.

2114
01:10:09,980 --> 01:10:11,500
Every new resource should be bicep,

2115
01:10:11,500 --> 01:10:12,940
not eventually, from now on.

2116
01:10:12,940 --> 01:10:14,540
When a team wants to deploy something new,

2117
01:10:14,540 --> 01:10:15,820
they define it in bicep.

2118
01:10:15,820 --> 01:10:17,580
They go through the governance process.

2119
01:10:17,580 --> 01:10:19,180
They use the landing zone template.

2120
01:10:19,180 --> 01:10:20,700
They integrate with the module registry.

2121
01:10:20,700 --> 01:10:23,420
This decision alone that new things are always bicep

2122
01:10:23,420 --> 01:10:24,780
begins the transition.

2123
01:10:24,780 --> 01:10:27,180
Over time, new resources accumulate.

2124
01:10:27,180 --> 01:10:29,340
The bicep portion of your infrastructure grows.

2125
01:10:29,340 --> 01:10:31,020
Existing resources can be adopted

2126
01:10:31,020 --> 01:10:32,780
into bicep through export.

2127
01:10:32,780 --> 01:10:35,100
Azure has a feature that lets you export the template

2128
01:10:35,100 --> 01:10:36,620
for any existing resource.

2129
01:10:36,620 --> 01:10:38,220
You export a virtual network

2130
01:10:38,220 --> 01:10:40,460
that was created manually through the portal.

2131
01:10:40,460 --> 01:10:41,660
You get an arm template.

2132
01:10:41,660 --> 01:10:44,220
That template becomes the basis for your network module.

2133
01:10:44,220 --> 01:10:45,100
It's messy.

2134
01:10:45,100 --> 01:10:47,260
The exported template includes every parameter,

2135
01:10:47,260 --> 01:10:49,740
every property, most of which you don't actually care about.

2136
01:10:49,740 --> 01:10:50,780
But it's a starting point.

2137
01:10:50,780 --> 01:10:51,740
You refactor it.

2138
01:10:51,740 --> 01:10:53,020
You strip out the noise.

2139
01:10:53,020 --> 01:10:54,380
You parameterize the decisions.

2140
01:10:54,380 --> 01:10:55,340
You add documentation.

2141
01:10:55,340 --> 01:10:57,340
The exported template becomes your module.

2142
01:10:57,340 --> 01:10:59,500
This adoption process works for individual resources

2143
01:10:59,500 --> 01:11:01,340
or for entire resource groups.

2144
01:11:01,340 --> 01:11:02,940
Export everything in a resource group.

2145
01:11:02,940 --> 01:11:05,660
You get one large template that defines the whole group.

2146
01:11:05,660 --> 01:11:07,740
Now you decide how to split it into modules.

2147
01:11:07,740 --> 01:11:09,420
Maybe one module per resource type.

2148
01:11:09,420 --> 01:11:11,580
Maybe one module per logical architecture layer.

2149
01:11:11,580 --> 01:11:14,220
The refactoring is work, but it's work you can do safely.

2150
01:11:14,220 --> 01:11:15,740
The resources already exist.

2151
01:11:15,740 --> 01:11:17,020
You're not creating anything new.

2152
01:11:17,020 --> 01:11:18,940
You're just creating a bicep representation

2153
01:11:18,940 --> 01:11:20,300
of what's already there.

2154
01:11:20,300 --> 01:11:22,380
The governance question surfaces immediately.

2155
01:11:22,380 --> 01:11:23,820
What's your migration strategy?

2156
01:11:23,820 --> 01:11:25,020
Which workloads move first?

2157
01:11:25,020 --> 01:11:25,980
This isn't academic.

2158
01:11:25,980 --> 01:11:27,340
It has real consequences.

2159
01:11:27,340 --> 01:11:28,780
Some teams will have dependencies

2160
01:11:28,780 --> 01:11:30,140
on other teams' infrastructure.

2161
01:11:30,140 --> 01:11:31,980
If you migrate a networking infrastructure first,

2162
01:11:31,980 --> 01:11:33,580
but the application teams aren't ready

2163
01:11:33,580 --> 01:11:35,180
to handle parameterized networks,

2164
01:11:35,180 --> 01:11:36,380
you create friction.

2165
01:11:36,380 --> 01:11:38,220
Better to think through the dependency graph.

2166
01:11:38,220 --> 01:11:40,780
Identify what can safely move independently.

2167
01:11:40,780 --> 01:11:41,580
Start there.

2168
01:11:41,580 --> 01:11:42,540
Build momentum.

2169
01:11:42,540 --> 01:11:45,180
Let success in one area create demand in another.

2170
01:11:45,180 --> 01:11:47,340
Brownfield environments are fundamentally messy.

2171
01:11:47,340 --> 01:11:48,780
You're not cleaning a blank slate.

2172
01:11:48,780 --> 01:11:51,020
You're renovating a house someone's been living in.

2173
01:11:51,020 --> 01:11:52,380
They've made modifications.

2174
01:11:52,380 --> 01:11:55,260
Things connect in ways the original architects didn't intend.

2175
01:11:55,260 --> 01:11:57,180
You'll find resources that are no longer in use,

2176
01:11:57,180 --> 01:11:58,460
but nobody's deleted them.

2177
01:11:58,460 --> 01:11:59,980
You'll find manual configurations

2178
01:11:59,980 --> 01:12:01,740
that don't match any documentation.

2179
01:12:01,740 --> 01:12:03,580
You'll find policies that contradict each other.

2180
01:12:03,580 --> 01:12:04,780
Bicep should be the target state,

2181
01:12:04,780 --> 01:12:07,260
but the actual state is going to require cleanup.

2182
01:12:07,260 --> 01:12:08,540
The principle is straightforward,

2183
01:12:08,540 --> 01:12:10,220
but often tested in practice.

2184
01:12:10,220 --> 01:12:12,540
Every new resource should be bicep.

2185
01:12:12,540 --> 01:12:14,380
Not every important resource.

2186
01:12:14,380 --> 01:12:17,020
Not every resource we have budget to migrate.

2187
01:12:17,020 --> 01:12:17,980
Every resource.

2188
01:12:17,980 --> 01:12:19,980
This means when developers want to deploy something

2189
01:12:19,980 --> 01:12:21,180
they write bicep.

2190
01:12:21,180 --> 01:12:22,780
When operators need to make changes,

2191
01:12:22,780 --> 01:12:24,140
they modify bicep.

2192
01:12:24,140 --> 01:12:26,220
When new capabilities ship in Azure teams

2193
01:12:26,220 --> 01:12:28,380
who want them write bicep to implement them.

2194
01:12:28,380 --> 01:12:31,500
The investment shifts from managing existing messy infrastructure

2195
01:12:31,500 --> 01:12:34,060
toward building bicep definitions of new infrastructure.

2196
01:12:34,060 --> 01:12:35,500
Gradually, in this takes time,

2197
01:12:35,500 --> 01:12:37,100
measured in years, not months.

2198
01:12:37,100 --> 01:12:39,180
The entire state becomes code driven.

2199
01:12:39,180 --> 01:12:41,820
Old portal-created resources eventually get decommissioned

2200
01:12:41,820 --> 01:12:43,660
and replaced with bicep versions.

2201
01:12:43,660 --> 01:12:46,220
Legacy arm templates get refacted into modules.

2202
01:12:46,220 --> 01:12:48,220
Manual configurations get captured as code.

2203
01:12:48,220 --> 01:12:49,580
You don't finish the migration.

2204
01:12:49,580 --> 01:12:51,340
You complete specific phases.

2205
01:12:51,340 --> 01:12:54,060
Each phase leaves you in a better state than you started.

2206
01:12:54,060 --> 01:12:56,540
More predictable, more governed, more maintainable.

2207
01:12:56,540 --> 01:12:58,060
That's how you transform a brownfield

2208
01:12:58,060 --> 01:12:59,260
into a controlled platform.

2209
01:12:59,260 --> 01:13:01,820
The 2026 landscape, what's changing?

2210
01:13:01,820 --> 01:13:03,580
The Azure platform doesn't stand still

2211
01:13:03,580 --> 01:13:05,660
and neither does the role bicep plays in it.

2212
01:13:05,660 --> 01:13:06,940
Looking at 2026,

2213
01:13:06,940 --> 01:13:08,780
several shifts are happening simultaneously.

2214
01:13:08,780 --> 01:13:10,060
They're not separate developments.

2215
01:13:10,060 --> 01:13:11,820
They're pieces of a coherent movement

2216
01:13:11,820 --> 01:13:14,780
toward infrastructure as the control plane of the organization.

2217
01:13:14,780 --> 01:13:16,780
Azure blueprints officially disappeared.

2218
01:13:16,780 --> 01:13:18,300
July 2026.

2219
01:13:18,300 --> 01:13:19,900
This isn't a surprise that's coming.

2220
01:13:19,900 --> 01:13:20,940
It's already here.

2221
01:13:20,940 --> 01:13:23,420
Blueprints were Microsoft's first attempt at solving the

2222
01:13:23,420 --> 01:13:25,420
"How do we govern at scale problem?"

2223
01:13:25,420 --> 01:13:27,820
They bundled templates with policies and role assignments.

2224
01:13:27,820 --> 01:13:29,980
They could assign those bundles to management groups.

2225
01:13:29,980 --> 01:13:31,180
But they hit a ceiling.

2226
01:13:31,180 --> 01:13:33,100
They weren't versioned like modern software is.

2227
01:13:33,100 --> 01:13:35,020
They weren't integrated with CI/CD.

2228
01:13:35,020 --> 01:13:36,380
They were difficult to maintain.

2229
01:13:36,380 --> 01:13:37,900
Deployment stacks replace them.

2230
01:13:37,900 --> 01:13:39,580
Stacks are native Azure resources.

2231
01:13:39,580 --> 01:13:40,300
They're versioned.

2232
01:13:40,300 --> 01:13:41,580
They integrate with everything else.

2233
01:13:41,580 --> 01:13:42,700
They have state awareness.

2234
01:13:42,700 --> 01:13:44,300
They work seamlessly in pipelines.

2235
01:13:44,300 --> 01:13:46,860
The migration from blueprints to stacks matters

2236
01:13:46,860 --> 01:13:48,940
because it signals that governance infrastructure

2237
01:13:48,940 --> 01:13:51,260
is now treated like application infrastructure.

2238
01:13:51,260 --> 01:13:53,420
Deployment stacks themselves are getting richer.

2239
01:13:53,420 --> 01:13:55,020
The deny settings we've talked about,

2240
01:13:55,020 --> 01:13:57,580
those hard protections against unintended modification

2241
01:13:57,580 --> 01:13:59,660
are becoming the standard governance pattern.

2242
01:13:59,660 --> 01:14:01,420
De deny settings prevents certain actions

2243
01:14:01,420 --> 01:14:03,020
on stack managed resources.

2244
01:14:03,020 --> 01:14:05,020
This shifts how people think about access control.

2245
01:14:05,020 --> 01:14:06,620
You don't just ask who can deploy.

2246
01:14:06,620 --> 01:14:09,420
You ask what they can modify once it's deployed.

2247
01:14:09,420 --> 01:14:11,100
Life cycle controls around deletion

2248
01:14:11,100 --> 01:14:13,420
and detachment are becoming more sophisticated.

2249
01:14:13,420 --> 01:14:15,260
Organizations can now configure stacks

2250
01:14:15,260 --> 01:14:17,100
differently in different environments.

2251
01:14:17,100 --> 01:14:19,740
Aggressive cleanup in dev, conservative protection in prod,

2252
01:14:19,740 --> 01:14:21,500
all expressed as configuration

2253
01:14:21,500 --> 01:14:23,020
not as separate processes.

2254
01:14:23,020 --> 01:14:25,900
EntraID resources now have general availability bicep support.

2255
01:14:25,900 --> 01:14:28,140
This is significant because it completes the picture.

2256
01:14:28,140 --> 01:14:30,700
Identity used to be something you configured separately.

2257
01:14:30,700 --> 01:14:32,620
You deploy infrastructure in bicep.

2258
01:14:32,620 --> 01:14:34,940
Then separately you'd set up identity integration.

2259
01:14:34,940 --> 01:14:35,820
It was fragmented.

2260
01:14:35,820 --> 01:14:38,380
Now identity is part of the infrastructure definition.

2261
01:14:38,380 --> 01:14:40,220
You define service principles in bicep.

2262
01:14:40,220 --> 01:14:43,020
Managed identities, conditional access policies,

2263
01:14:43,020 --> 01:14:46,140
role assignments, all in the same code base as everything else.

2264
01:14:46,140 --> 01:14:48,300
Identity as code isn't theoretical anymore.

2265
01:14:48,300 --> 01:14:51,260
It's operational as your verified modules continue expanding.

2266
01:14:51,260 --> 01:14:53,900
More resources, more patents, more standardization.

2267
01:14:53,900 --> 01:14:55,900
Where once AVM was a curated collection

2268
01:14:55,900 --> 01:14:57,580
it's becoming the expected baseline.

2269
01:14:57,580 --> 01:15:00,460
New resources in Azure Ship with corresponding AVM modules.

2270
01:15:00,460 --> 01:15:01,820
Not eventually, not next quarter,

2271
01:15:01,820 --> 01:15:03,260
alongside the resource itself,

2272
01:15:03,260 --> 01:15:05,020
this accelerates the adoption of standards.

2273
01:15:05,020 --> 01:15:07,660
Teams don't have to decide how to configure something novel.

2274
01:15:07,660 --> 01:15:09,420
AVM already has a recommended approach.

2275
01:15:09,420 --> 01:15:11,900
It's tested, it's documented, it's versioned.

2276
01:15:11,900 --> 01:15:14,860
The ecosystem is converging in an important way.

2277
01:15:14,860 --> 01:15:17,900
Bicep and Terraform AVM modules follow the same specifications.

2278
01:15:17,900 --> 01:15:20,140
The same parameter patterns, the same outputs,

2279
01:15:20,140 --> 01:15:21,980
the same documentation structure.

2280
01:15:21,980 --> 01:15:25,740
This convergence means architectural standards become tool independent.

2281
01:15:25,740 --> 01:15:27,740
You can standardize on how networks should work,

2282
01:15:27,740 --> 01:15:29,020
how identity should integrate,

2283
01:15:29,020 --> 01:15:30,780
how compliance should be enforced

2284
01:15:30,780 --> 01:15:32,860
and then teams can implement those standards

2285
01:15:32,860 --> 01:15:35,420
in bicep or Terraform depending on their context.

2286
01:15:35,420 --> 01:15:37,580
The standards aren't locked to a language.

2287
01:15:37,580 --> 01:15:39,820
Infrastructure code is becoming the control plane.

2288
01:15:39,820 --> 01:15:41,500
Not the mechanism for deploying things,

2289
01:15:41,500 --> 01:15:42,780
the mechanism for governing them,

2290
01:15:42,780 --> 01:15:45,340
for controlling them, for ensuring they don't drift,

2291
01:15:45,340 --> 01:15:47,820
for assigning ownership, for tracking life cycle.

2292
01:15:47,820 --> 01:15:49,020
Bicep is the vehicle,

2293
01:15:49,020 --> 01:15:50,860
but the concept extends beyond it.

2294
01:15:50,860 --> 01:15:52,620
The platform itself, the management groups,

2295
01:15:52,620 --> 01:15:54,380
the policies, the deployment stacks,

2296
01:15:54,380 --> 01:15:55,500
the role assignments,

2297
01:15:55,500 --> 01:15:57,020
all of it is now defined in code.

2298
01:15:57,020 --> 01:15:59,660
This is the transition from infrastructure as code

2299
01:15:59,660 --> 01:16:01,980
as a deployment convenience to infrastructure as code

2300
01:16:01,980 --> 01:16:03,340
as organizational governance.

2301
01:16:03,340 --> 01:16:07,100
Organizations adopting this model now have a significant competitive advantage.

2302
01:16:07,100 --> 01:16:08,780
Not in speed, though they'll be faster,

2303
01:16:08,780 --> 01:16:09,980
but in predictability.

2304
01:16:09,980 --> 01:16:13,420
In compliance, in the ability to adapt when business needs change,

2305
01:16:13,420 --> 01:16:15,500
when a merger happens and you suddenly need to integrate

2306
01:16:15,500 --> 01:16:17,420
another organization's Azure footprint,

2307
01:16:17,420 --> 01:16:18,940
you don't negotiate how you'll govern it.

2308
01:16:18,940 --> 01:16:20,300
You don't manually configure it,

2309
01:16:20,300 --> 01:16:21,580
you have a template,

2310
01:16:21,580 --> 01:16:22,540
you instantiate it,

2311
01:16:22,540 --> 01:16:24,380
you've already codified how governance works.

2312
01:16:24,380 --> 01:16:26,380
It's not a project, it's a deployment.

2313
01:16:26,380 --> 01:16:29,740
The organizations that haven't adopted this model by 2026

2314
01:16:29,740 --> 01:16:31,580
are increasingly at a disadvantage.

2315
01:16:31,580 --> 01:16:33,180
They're still managing infrastructure

2316
01:16:33,180 --> 01:16:35,020
through change management conversations,

2317
01:16:35,020 --> 01:16:37,340
through ticket systems, through manual approvals,

2318
01:16:37,340 --> 01:16:39,660
their hoping configurations stay consistent,

2319
01:16:39,660 --> 01:16:42,620
bicep and the practices around it eliminate that guesswork.

2320
01:16:42,620 --> 01:16:44,140
bicep isn't syntax,

2321
01:16:44,140 --> 01:16:47,260
it's the architecture of organizational governance expressed in code.

2322
01:16:47,260 --> 01:16:49,740
The separation between hobby projects and enterprise

2323
01:16:49,740 --> 01:16:51,260
is life cycle awareness,

2324
01:16:51,260 --> 01:16:53,500
contract enforcement and state visibility.

2325
01:16:53,500 --> 01:16:55,500
Deployment stacks, Azure verified modules

2326
01:16:55,500 --> 01:16:57,580
and management groups goaps aren't features.

2327
01:16:57,580 --> 01:16:58,940
They're evidence of this shift,

2328
01:16:58,940 --> 01:17:01,980
their proof that infrastructure code has become the control plane.

2329
01:17:01,980 --> 01:17:03,740
Start with modules, publish them,

2330
01:17:03,740 --> 01:17:05,980
enforce their use, your entire infrastructure

2331
01:17:05,980 --> 01:17:08,780
becomes a reflection of your organizational principles,

2332
01:17:08,780 --> 01:17:11,340
not an afterthought to your business operations.

Mirko Peters Profile Photo

Founder of m365.fm, m365.show and m365con.net

Mirko Peters is a Microsoft 365 expert, content creator, and founder of m365.fm, a platform dedicated to sharing practical insights on modern workplace technologies. His work focuses on Microsoft 365 governance, security, collaboration, and real-world implementation strategies.

Through his podcast and written content, Mirko provides hands-on guidance for IT professionals, architects, and business leaders navigating the complexities of Microsoft 365. He is known for translating complex topics into clear, actionable advice, often highlighting common mistakes and overlooked risks in real-world environments.

With a strong emphasis on community contribution and knowledge sharing, Mirko is actively building a platform that connects experts, shares experiences, and helps organizations get the most out of their Microsoft 365 investments.