July 6, 2026

The PowerShell Ceiling: Why You Need Bicep

The PowerShell Ceiling: Why You Need Bicep
The PowerShell Ceiling: Why You Need Bicep
M365 FM Podcast
The PowerShell Ceiling: Why You Need Bicep

PowerShell has become the automation standard for Microsoft environments, but it reaches its limits when managing modern cloud infrastructure at scale. In this episode, we explore why Azure Bicep has become the preferred Infrastructure as Code (IaC) language for deploying and maintaining Azure resources, and why relying solely on PowerShell can create long-term operational challenges.

The discussion explains the fundamental differences between imperative and declarative automation. While PowerShell focuses on executing commands step by step, Bicep describes the desired end state of your infrastructure, allowing Azure Resource Manager to handle deployments consistently, repeatably, and idempotently.

You'll learn why Bicep simplifies infrastructure management through reusable modules, parameterized deployments, and native Azure integration. The episode also covers how Bicep improves collaboration between architects, developers, and operations teams by making infrastructure easier to version, review, and maintain using modern DevOps practices.

Rather than replacing PowerShell entirely, the conversation highlights how the two technologies complement each other. PowerShell remains the ideal tool for operational automation, scripting, and administration, while Bicep should be used to provision and manage Azure infrastructure in a predictable and scalable way.

Whether you're an Azure administrator, cloud architect, or DevOps engineer, this episode provides practical guidance on when to use PowerShell, when to adopt Bicep, and how combining both tools creates a more reliable, maintainable, and enterprise-ready Azure environment.

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

Managing Azure resources with PowerShell can become complex and cumbersome. You may find yourself facing the PowerShell ceiling, where the intricacies of script management hinder your efficiency. The syntax often feels convoluted, making it challenging to maintain and scale your infrastructure. In contrast, Bicep emerges as a modern solution that simplifies deploying Azure resources. It uses declarative infrastructure as code principles, allowing you to define your resources clearly and concisely. This shift not only enhances readability but also streamlines your resource management process.

Key Takeaways

  • PowerShell can be complex and hard to manage, especially as your Azure resources grow.
  • Bicep simplifies Azure resource management with a clearer and more readable syntax.
  • Using Bicep allows for modular development, making it easier to reuse code and maintain projects.
  • Bicep provides strong type checking, helping to catch errors early in the development process.
  • Transitioning to Bicep can improve team collaboration by making code easier to understand.
  • Bicep integrates well with Azure services, enhancing governance and compliance in resource management.
  • While Bicep has a learning curve, its benefits can lead to more efficient and organized deployments.
  • Bicep is specifically designed for Azure, making it unsuitable for multi-cloud environments.

PowerShell Limitations

PowerShell Limitations

Using PowerShell for Azure resource management often presents several significant challenges. As IT professionals, you may encounter issues that impede your ability to work efficiently and effectively. Here are some of the common limitations:

Syntax Complexity

PowerShell’s syntax can feel daunting. The unique parsing mechanisms found in its command syntax differ from those of other languages, which can lead to confusion and errors. Users often struggle with:

  • Special characters: PowerShell's treatment of these characters can introduce unexpected behavior in scripts.
  • Quoting differences: Understanding how to correctly use quotes around parameters can trip you up and lead to frustrating bug hunts.

Due to these complexities, many scripts experience higher error rates. For instance, you might create a command, but it fails due to a minor syntactical mistake. Proper error handling, such as incorporating try and catch mechanisms, becomes essential to manage these issues seamlessly.

Scalability Challenges

As your organization grows, scaling your Azure resources can become cumbersome with PowerShell. Users commonly report encountering limits on the number of resources when migrating workloads to Azure. These limits can hinder your ability to expand as needed. Keep in mind:

  • There are adjustments available upon request for specific consumption limitations.
  • Being aware of these restrictions is crucial for effective resource management.

Without a structured approach to scaling, managing an increasing number of resources can lead to chaos and decreased operational efficiency.

Documentation Issues

Documentation plays a vital role in managing Azure resources effectively. However, the quality and availability of PowerShell documentation can often fall short. You may notice:

  • Many users struggle to find excellent documentation, leading to wasted time trying to understand how to perform tasks.
  • Automation through PowerShell can accelerate operations, but if documentation is lacking, it can negatively impact productivity.

With improved documentation and clarity, you could more easily adapt your scripts to meet enterprise needs, ultimately leading to minimized downtime and enhanced operational efficiency.

To overcome these PowerShell limitations, consider adopting structured approaches like Infrastructure as Code (IaC). Table 1 below highlights some effective strategies:

Approach/ToolDescriptionUsage
Infrastructure as Code (IaC)Automates resource management using configuration scripts.Versioned configurations for collaboration.
TerraformOpen-source tool using HCL for infrastructure management.Deployment via Terraform command line.
BicepSimplified deployment language for Azure, more readable than JSON.Deployment via Azure CLI or PowerShell.
Azure Resource Manager (ARM) TemplatesUses JSON to declaratively define and deploy Azure resources.Deployment via the Azure portal or CLI.
Azure PowerShellPowerShell module for Azure resource management.Deployment via PowerShell scripts.

Embracing these structured solutions can empower you and your team to surpass the limitations of PowerShell.

What is Bicep?

Bicep is a domain-specific language designed to simplify the deployment of Azure resources. It serves as a more user-friendly alternative to traditional Azure Resource Manager (ARM) templates, which often involve complex JSON syntax. With Bicep, you can define your infrastructure in a clear and concise manner, making it easier to manage and maintain.

Definition and Purpose

The primary purpose of Bicep is to streamline the authoring experience for Infrastructure as Code (IaC). It allows you to focus on defining the desired state of your resources without getting bogged down by intricate syntax. Here are some key purposes of Bicep:

  1. Simplified Syntax: Bicep uses a simplified and human-friendly syntax that is more readable than ARM templates.
  2. Modularity: Bicep supports module-based development, allowing for reusable modules.
  3. Type Safety: Bicep provides strong type checking to catch errors early.
  4. Code Reusability: Bicep enables easy definition and reuse of complex resource configurations.
  5. Incremental Deployment: Bicep supports updating only changed resources.

This approach not only enhances your productivity but also reduces the likelihood of errors during deployment.

Key Features

Bicep offers several features that distinguish it from PowerShell and traditional ARM templates. These features enhance your experience when managing Azure resources.

Simplicity and Readability

Bicep's syntax is cleaner and more readable compared to the verbose JSON used in ARM templates. You can write shorter and easier-to-maintain Bicep files. This simplicity allows you to focus on the logic of your infrastructure rather than wrestling with complex syntax.

FeatureBicepTraditional ARM Templates
SyntaxCleaner and more readableJSON-based, more complex
File LengthShorter and easier to maintainLonger and harder to manage
ModularitySupports reusable modulesTypically one large file
Dependency ManagementAutomatically detects dependenciesManual management required

Modularization

Bicep's modularization feature significantly impacts large-scale Azure infrastructure projects. You can create reusable modules that simplify both maintenance and scaling. This modular approach promotes consistency across projects and reduces duplication.

BenefitDescription
Code ReusabilityBicep supports modular design, allowing developers to create reusable components.
ConsistencyModules can be shared across projects, promoting consistency and reducing duplication.
Simplified ManagementThis modular approach simplifies the management of complex infrastructures.

By adopting Bicep, you can transform your Azure resource management into a more organized and efficient process.

Bicep Strengths

Bicep offers several advantages that significantly enhance your experience when deploying Azure resources. By simplifying the process and improving collaboration, Bicep empowers you to manage your infrastructure more effectively.

Enhanced Deployment Experience

With Bicep, you enjoy an enhanced deployment experience that streamlines your workflow. Here are some key benefits:

  • Bicep's syntax is simpler and more concise than ARM templates, which reduces clutter and improves readability.
  • It offers enhanced tooling support, including IntelliSense and code linting, which boosts developer productivity.
  • By simplifying the syntax, Bicep reduces the learning curve for developers, making it easier to create and manage Azure resources.

These features allow you to focus on what matters most—deploying your resources efficiently and accurately.

Improved Collaboration

Bicep fosters improved collaboration among Azure development teams. The clean and readable syntax enhances understanding and maintenance, making it easier for team members to work together. Here are some ways Bicep facilitates collaboration:

  • The ability to create reusable Bicep modules standardizes complex components, streamlining collaboration across projects.
  • Bicep's strong tools and type safety help catch errors early, leading to fewer deployment failures and a more confident delivery process.
  • Integration with CI/CD pipelines ensures that changes are traceable and consistently applied, improving operational efficiency.

The transition from JSON-based ARM templates to Bicep has transformed the Cloud Engineering Services team at Microsoft. This shift has enhanced efficiency and security, allowing teams to work more effectively with modern CI/CD solutions. As a result, you can expect better code quality and reduced maintenance overhead.

Integration with Azure Services

Bicep integrates seamlessly with Azure services, enhancing governance and compliance in your resource management. You can create policy definitions that enforce security measures, such as limiting App Service SKUs and ensuring secure connections. For example, a policy can deny the deployment of an App Service if it does not comply with HTTPS requirements. This capability strengthens your governance and compliance efforts.

Bicep supports the following key governance features:

  • Policy Definitions: Core rules that specify conditions for policies, allowing for both built-in and custom definitions.
  • Policy Assignments: Application of policy definitions to specific scopes, ensuring enforcement where needed.
  • Policy Sets (Initiatives): Grouping of multiple policy definitions for easier management and consistent application.

By leveraging these features, you can ensure that your Azure resources adhere to organizational standards and regulatory requirements.

Bicep Weaknesses

While Bicep offers many advantages, it also has some weaknesses that you should consider before adopting it for your Azure resource management.

Learning Curve

Transitioning to Bicep may present a learning curve for you. Although Bicep simplifies many aspects of resource management, it still requires you to understand its syntax and structure. For instance, Bicep is sensitive to new lines, which can complicate the writing process. You might find yourself troubleshooting issues that arise from formatting errors. Additionally, the apiProfile feature, which would allow mapping to specific API versions, is currently unsupported. This limitation can hinder your ability to work with certain Azure resources effectively.

Limited Community Support

Bicep's community is still developing, which means you may encounter fewer resources compared to more established tools like Terraform. The smaller community can lead to challenges in finding examples, tutorials, and modules that can help you get started. As Bicep continues to grow, the community will likely expand, but you may need to rely on official documentation and forums for support in the meantime.

Tooling and Ecosystem

Bicep has some limitations in its tooling and ecosystem that you should be aware of. Here’s a summary of the key limitations:

Limitation TypeDescription
Azure ExclusivityBicep is limited to Azure, making it unsuitable for multi-cloud deployments.
Relative ImmaturityLacks features and tooling compared to more established tools like Terraform.
Smaller CommunityBicep has a smaller community and ecosystem compared to Terraform, though it is growing.

You cannot manage AWS, GCP, on-prem, or SaaS providers with Bicep, which limits its use in multi-cloud or hybrid scenarios. Additionally, Bicep architectures are tightly coupled to Azure Resource Manager (ARM), making reuse outside Azure challenging. You may find fewer community modules, patterns, and integrations compared to Terraform’s extensive ecosystem.

Comparing Bicep and PowerShell

Syntax and Usability

When you compare Bicep and PowerShell, syntax simplicity stands out as a key difference. Bicep is designed to be user-friendly, making it easier for you to write and maintain your code. Many users find Bicep's approach more concise and readable than traditional JSON-based ARM templates. This clarity helps you focus on defining your infrastructure without getting lost in complex syntax. Bicep serves as a Domain Specific Language (DSL) for deploying Azure resources in a declarative way, which simplifies the experience of using ARM templates.

In contrast, PowerShell can feel overwhelming due to its intricate syntax. You may struggle with special characters and quoting differences, which can lead to errors. The learning curve for PowerShell can be steep, especially when managing large scripts. Therefore, if you prioritize ease of use and readability, Bicep is likely the better choice.

Performance and Efficiency

Performance is another area where Bicep shines. Bicep supports rapid deployment while maintaining a clear structure, which is beneficial for team collaboration. Its modular design allows you to break down complex configurations into manageable pieces. This modularity enhances efficiency, as you can reuse components across different projects.

PowerShell, while powerful, may not offer the same level of efficiency for large-scale deployments. As your infrastructure grows, you might find that managing numerous scripts becomes cumbersome. The PowerShell ceiling can limit your ability to scale effectively. In contrast, Bicep's streamlined approach allows you to manage your Azure resources more efficiently, reducing the time spent on deployment tasks.

Use Cases

Choosing between Bicep and PowerShell often depends on your specific use case. Here are some scenarios where Bicep may be preferable:

ScenarioReason for Preference
Simplified syntaxBicep offers a more human-readable syntax than PowerShell, making it easier to write and maintain.
Modern projectsIdeal for teams transitioning from raw JSON to a more structured approach.
Rapid deployment with structureBicep supports quick deployments while maintaining a clear structure, which is beneficial for team collaboration.

In situations where you need to manage existing ARM templates, Bicep can simplify the process. You can convert your existing ARM templates into Bicep files, allowing you to take advantage of its readability and modularity. This transition can help you overcome the limitations of PowerShell and enhance your overall deployment strategy.


In summary, adopting Bicep for Azure resource management offers numerous advantages over PowerShell. You benefit from a concise syntax that enhances readability and simplifies code reviews. Bicep's structure allows for clean organization, with each resource in its own module file. This modularity promotes code reuse and reduces complexity.

Additionally, Bicep provides excellent tooling support, including IntelliSense and linting, which help catch errors before deployment. With built-in dependency management and resource visualization, you can manage your Azure infrastructure more effectively. Overall, Bicep empowers you to streamline your deployment processes and improve collaboration within your team.

FAQ

What is Bicep?

Bicep is a domain-specific language designed to simplify Azure resource deployment. It offers a more readable syntax than traditional ARM templates, making it easier for you to manage infrastructure as code.

How does Bicep improve collaboration?

Bicep enhances collaboration by providing a clear and concise syntax. This readability allows team members to understand and maintain code easily, fostering better teamwork and reducing errors during deployment.

Can I use Bicep for multi-cloud deployments?

No, Bicep is specifically designed for Azure. If you need to manage resources across multiple cloud providers, consider using tools like Terraform, which support multi-cloud environments.

How do I convert existing ARM templates to Bicep?

You can use the Bicep CLI to decompile existing ARM templates into Bicep files. This process simplifies your transition to Bicep, allowing you to leverage its benefits while maintaining your current infrastructure.

Is Bicep suitable for beginners?

Yes, Bicep is beginner-friendly due to its simplified syntax. You can quickly learn to define Azure resources without getting overwhelmed by complex JSON structures, making it an excellent choice for newcomers.

What tooling support does Bicep offer?

Bicep provides excellent tooling support, including IntelliSense and code linting. These features help you catch errors early and improve your overall development experience when managing Azure resources.

How does Bicep handle dependencies?

Bicep automatically manages resource dependencies, ensuring that resources are deployed in the correct order. This feature simplifies your deployment process and reduces the likelihood of errors related to resource dependencies.

Where can I find Bicep documentation?

You can find comprehensive Bicep documentation on the official Microsoft website. This resource includes tutorials, examples, and best practices to help you get started with Bicep effectively.

🚀 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,640
You have 50 scripts. They work. Every single one does what it is supposed to do.

2
00:00:03,640 --> 00:00:06,440
You wrote them, your team runs them and they solve real problems.

3
00:00:06,440 --> 00:00:09,720
But here is the tension. Nobody talks about nobody knows why anymore.

4
00:00:09,720 --> 00:00:13,560
Ask yourself who deployed the automation account that runs your biggest workflow,

5
00:00:13,560 --> 00:00:17,280
or when it was actually set up. Think about what permissions it has and where the key

6
00:00:17,280 --> 00:00:20,400
vault is that stores those connection strings. If that subscription disappeared

7
00:00:20,400 --> 00:00:24,120
tomorrow, could you rebuild this in three hours? Or would it take three weeks of

8
00:00:24,120 --> 00:00:27,640
reverse engineering your own scripts? This is the real problem with automation at

9
00:00:27,640 --> 00:00:31,400
scale. It does not fail because the scripts are bad. It fails because automation

10
00:00:31,400 --> 00:00:34,720
that scales becomes infrastructure that nobody can govern. You have built

11
00:00:34,720 --> 00:00:38,080
something that works, but you have not built something that is repeatable,

12
00:00:38,080 --> 00:00:41,800
auditable, or defensible. In this episode, we are moving from doing things to

13
00:00:41,800 --> 00:00:44,800
defining systems. You will understand why PowerShell hits a ceiling.

14
00:00:44,800 --> 00:00:48,320
Not because PowerShell is bad, but because PowerShell is designed for

15
00:00:48,320 --> 00:00:52,240
actions, not for defining infrastructure. And you will see how bicep becomes the

16
00:00:52,240 --> 00:00:55,880
foundation for real platform engineering. It is the language that lets you treat

17
00:00:55,880 --> 00:01:00,200
your infrastructure the way software engineers treat code, versioned, reviewed,

18
00:01:00,200 --> 00:01:05,480
auditable, repeatable. By the end, you will know exactly where you are on this

19
00:01:05,480 --> 00:01:09,200
journey and what the next level looks like. The automation journey, how you got

20
00:01:09,200 --> 00:01:12,760
here. Let me walk you through how almost every engineer ends up in this exact

21
00:01:12,760 --> 00:01:16,520
place. Phase one is always the same. You are in the portal, clicking, creating

22
00:01:16,520 --> 00:01:20,240
users one at a time, assigning licenses one at a time. It is repetitive and soul

23
00:01:20,240 --> 00:01:23,280
crushing. So one day you decide to script it. You write your first PowerShell

24
00:01:23,280 --> 00:01:27,200
script with 30 or 50 lines that does the job. You save it and run it. And suddenly

25
00:01:27,200 --> 00:01:30,880
what took an hour takes five minutes. That moment feels like magic. Then phase

26
00:01:30,880 --> 00:01:33,960
two starts. That one script works so well. You write another for a different

27
00:01:33,960 --> 00:01:38,000
problem. Do it once in code instead of manually. Now you have two scripts, then

28
00:01:38,000 --> 00:01:41,280
five, then 10. Each one solves a specific problem like user provisioning,

29
00:01:41,280 --> 00:01:45,760
license assignment, group management, or exchange configuration. They all work

30
00:01:45,760 --> 00:01:49,200
independently and solve real problems. By the time you hit 10 scripts, you are

31
00:01:49,200 --> 00:01:53,760
already saving the organization significant time. By 20 you are a hero. Your team

32
00:01:53,760 --> 00:01:57,280
depends on you and management notices. So you actually get budgeted for this

33
00:01:57,280 --> 00:02:01,760
work now. Then you hit phase three. Scripts are everywhere. You have 30, 40 or

34
00:02:01,760 --> 00:02:06,120
50 scripts, summer and shared folders, summer on your local drive, and summer

35
00:02:06,120 --> 00:02:09,840
and git repos that nobody has touched in 18 months. You start getting asked to

36
00:02:09,840 --> 00:02:13,240
modify an old script and you realize you cannot remember what it does. Or

37
00:02:13,240 --> 00:02:16,240
rather you remember the script, but you do not remember the infrastructure.

38
00:02:16,240 --> 00:02:19,680
It depends on which subscription is this supposed to run in? Where does it store

39
00:02:19,680 --> 00:02:22,960
its credentials? Who set up the service account that runs this? Here is the

40
00:02:22,960 --> 00:02:26,160
honest truth about this phase. You have automated tasks. You have not built a

41
00:02:26,160 --> 00:02:30,520
platform. A platform is repeatable, documented and auditable. It is governable.

42
00:02:30,520 --> 00:02:34,120
It can be deployed to different environments without manual intervention

43
00:02:34,120 --> 00:02:38,320
and recreated from source control. A platform is infrastructure. Your scripts

44
00:02:38,320 --> 00:02:41,680
are brilliant at doing one thing, but 50 scripts is not a platform. It is a

45
00:02:41,680 --> 00:02:45,360
collection of solutions. And the moment someone asks you to rebuild all of

46
00:02:45,360 --> 00:02:49,040
this in a new tenant or across Devon production or in a disaster recovery

47
00:02:49,040 --> 00:02:52,400
scenario, you realize the entire thing is fragile. This is the power shell

48
00:02:52,400 --> 00:02:55,600
ceiling. It is not a failure. It is a signal. It means you have outgrown the

49
00:02:55,600 --> 00:02:59,200
model. Scripting is designed for tasks, but infrastructure needs a different

50
00:02:59,200 --> 00:03:02,880
model entirely. And the moment you are managing dozens of scripts, multiple

51
00:03:02,880 --> 00:03:06,280
automation accounts, key vaults, storage accounts, monitoring solutions and

52
00:03:06,280 --> 00:03:10,480
service principles across subscriptions, you are not automating anymore. You are

53
00:03:10,480 --> 00:03:14,040
operating a platform, but your toolset is built for scripting. That mismatch is

54
00:03:14,040 --> 00:03:18,920
where the problem lives. What power shell actually is and what it isn't. Power

55
00:03:18,920 --> 00:03:22,000
shell is imperative. That sounds like a technical buzzword, but let's make it

56
00:03:22,000 --> 00:03:26,000
concrete. Imperative means you are giving commands step by step. Do this, then

57
00:03:26,000 --> 00:03:29,040
do that, then do this next thing. When you write a script, you're telling the

58
00:03:29,040 --> 00:03:33,280
system to create the user object, set the password and assign the license. You

59
00:03:33,280 --> 00:03:36,560
tell it to wait for that license to sync, add the user to a group and finally

60
00:03:36,560 --> 00:03:39,920
send a welcome email. Each line is an action and instruction. You are telling

61
00:03:39,920 --> 00:03:43,000
the machine to do something and power shell is brilliant at this because it was

62
00:03:43,000 --> 00:03:46,480
designed for it. If you have 100 users to onboard and want to do it in parallel,

63
00:03:46,480 --> 00:03:50,440
PowerShell handles that. If you need to query 30 groups to check memberships and

64
00:03:50,440 --> 00:03:54,480
report on licenses, PowerShell gets you the answer in seconds. The problem

65
00:03:54,480 --> 00:03:58,200
isn't what PowerShell does. The problem is what PowerShell doesn't do. PowerShell

66
00:03:58,200 --> 00:04:03,000
doesn't define infrastructure. Here is a practical example of where it breaks.

67
00:04:03,000 --> 00:04:07,880
You write a script that creates a user, assigns a Microsoft 365 license and adds

68
00:04:07,880 --> 00:04:11,440
them to a distribution group. The script runs, the user exists, the license is

69
00:04:11,440 --> 00:04:15,280
there, they are in the group. It works. But think about what that script doesn't say.

70
00:04:15,280 --> 00:04:18,040
It doesn't say who deployed it or where it runs from. It doesn't capture the

71
00:04:18,040 --> 00:04:21,880
credentials it uses or where those secrets are stored. It doesn't document the

72
00:04:21,880 --> 00:04:26,080
permissions it needs or define the automation account that executes the code. It

73
00:04:26,080 --> 00:04:29,280
doesn't specify which keyboard holds the connection strings and it doesn't

74
00:04:29,280 --> 00:04:32,680
declare what monitoring should be in place or where the logs should go. All of

75
00:04:32,680 --> 00:04:36,360
those things exist. Your script depends on them. But the script itself doesn't

76
00:04:36,360 --> 00:04:39,720
define them. It just assumes they're already there. That is the hidden problem

77
00:04:39,720 --> 00:04:43,120
with PowerShell at scale. When you have one script, this doesn't matter because

78
00:04:43,120 --> 00:04:46,320
you remember setting up the automation account last Tuesday. You know where the

79
00:04:46,320 --> 00:04:49,440
credentials live and you know exactly what prerequisites had to be in place for

80
00:04:49,440 --> 00:04:52,840
the code to run. But when you have 50 scripts, things change. You stop

81
00:04:52,840 --> 00:04:56,320
remembering. You stop knowing. And what's worse is that when someone new joins

82
00:04:56,320 --> 00:04:59,760
your team, they have to reverse engineer your infrastructure just by looking at

83
00:04:59,760 --> 00:05:03,360
your scripts. Except the scripts don't actually tell them the infrastructure.

84
00:05:03,360 --> 00:05:07,320
The scripts just use it. PowerShell tracks tasks. It executes actions. It moves

85
00:05:07,320 --> 00:05:11,400
data around and calls APIs to get things done. What PowerShell doesn't track is the

86
00:05:11,400 --> 00:05:15,480
desired state of your system. It doesn't say this is what should exist. It says go

87
00:05:15,480 --> 00:05:18,960
make this happen. That distinction matters more than it sounds because when you're

88
00:05:18,960 --> 00:05:22,920
managing a platform, not just running scripts, but managing the entire foundation

89
00:05:22,920 --> 00:05:26,800
those scripts depend on, you need to know what should exist. You need to know what

90
00:05:26,800 --> 00:05:29,560
version of the key vault should be deployed and what permissions it should have.

91
00:05:29,560 --> 00:05:32,880
You need to know if diagnostic logging is enabled, what the retention policy is,

92
00:05:32,880 --> 00:05:36,640
and who has access to the data. PowerShell can do any of those things, but it

93
00:05:36,640 --> 00:05:40,280
does them as actions rather than declarations. If someone manually changes a

94
00:05:40,280 --> 00:05:44,080
permission in the portal, PowerShell won't know it happened. If a key vault gets

95
00:05:44,080 --> 00:05:48,040
deleted, PowerShell won't recreate it unless you explicitly run a command to do so.

96
00:05:48,040 --> 00:05:51,920
There is no desired state that the system continuously enforces. PowerShell is a

97
00:05:51,920 --> 00:05:55,920
tool for doing things. It is not a tool for defining what things should be. That

98
00:05:55,920 --> 00:05:58,840
isn't a flaw. It's just what it is. And that's exactly why you need something else.

99
00:05:58,840 --> 00:06:03,200
The real cost of scripts brawl. Let's look at a scenario that probably sounds

100
00:06:03,200 --> 00:06:06,520
familiar. You've been building this automation platform for two years. It

101
00:06:06,520 --> 00:06:09,920
works. It's solid. And you've accumulated a lot of infrastructure to keep it

102
00:06:09,920 --> 00:06:13,840
running. You have 15 logic apps handling different workflows. Some trigger on

103
00:06:13,840 --> 00:06:17,440
a schedule, some respond to webhooks and others orchestrate complex multi-step

104
00:06:17,440 --> 00:06:21,280
processes. You have 10 automation accounts for different purposes, ranging from

105
00:06:21,280 --> 00:06:24,880
schedule jobs to managed identities for Azure integrations. You have 30 scripts

106
00:06:24,880 --> 00:06:27,960
spread across repositories, shared drives, and the automation accounts

107
00:06:27,960 --> 00:06:31,920
themselves. Some are functions inside logic apps. Some are standalone modules.

108
00:06:31,920 --> 00:06:35,640
Some are legacy scripts. You inherited that nobody wants to touch. Then you have

109
00:06:35,640 --> 00:06:39,600
five key vaults for secrets, three storage accounts for logs, and multiple service

110
00:06:39,600 --> 00:06:43,320
principles registered in enter ID. You're monitoring a scattered across different

111
00:06:43,320 --> 00:06:46,880
log analytics workspaces, and your resources are deployed across multiple

112
00:06:46,880 --> 00:06:50,560
subscriptions and resource groups. Now I'm going to ask you three questions. I

113
00:06:50,560 --> 00:06:53,720
want you to sit with the answer for a moment. First, who deployed all of this?

114
00:06:53,720 --> 00:06:58,680
When and why? You probably know the answer for the core pieces you built

115
00:06:58,680 --> 00:07:02,600
yourself, but there are parts you won't remember. That logic app handling incident

116
00:07:02,600 --> 00:07:07,600
is just a bit frustrating. Who set that up? Was it you two years ago or was it

117
00:07:07,600 --> 00:07:12,600
someone who left the team? Are there undocumented dependencies where a script in

118
00:07:12,600 --> 00:07:16,600
one account triggers a logic app that calls a function in another subscription?

119
00:07:16,600 --> 00:07:19,600
You think so, but you aren't entirely sure. Second question. If we lose this

120
00:07:19,600 --> 00:07:22,600
subscription tomorrow, can you rebuild this in three hours? I'm not asking if you

121
00:07:22,600 --> 00:07:26,600
could rebuild it eventually. I'm asking if you could recreate the entire platform

122
00:07:26,600 --> 00:07:30,600
from scratch with every dependency and configuration intact in a single

123
00:07:30,600 --> 00:07:34,600
site. First, we have backups. We can restore full capability in a predictable

124
00:07:34,600 --> 00:07:38,600
time frame. You probably can't do it. Most teams can't. You would need to

125
00:07:38,600 --> 00:07:42,600
remember the exact order you deployed things and recreate the service

126
00:07:42,600 --> 00:07:45,600
principles in the right way. You would have to provision the key vaults, populate

127
00:07:45,600 --> 00:07:48,600
them with secrets, and remember which storage accounts are needed for which

128
00:07:48,600 --> 00:07:52,600
purpose. You would need to redeploy all 15 logic apps and make sure they reference

129
00:07:52,600 --> 00:07:56,600
the correct accounts and reestablish every identity permission. Could you do it?

130
00:07:56,600 --> 00:08:00,600
But would it take three hours? Or would it take three weeks of reverse engineering

131
00:08:00,600 --> 00:08:04,600
your own work? Third question. Are we compliant and are we secured? This one cuts

132
00:08:04,600 --> 00:08:07,600
deeper because compliance and security aren't things you check once and forget

133
00:08:07,600 --> 00:08:11,600
about. They are continuous. Your organization has standards. All automation

134
00:08:11,600 --> 00:08:15,600
accounts should have diagnostic logging. All key vaults should have soft delete

135
00:08:15,600 --> 00:08:19,600
turned on. All secrets should have expiration policies. Do your 15 logic apps and

136
00:08:19,600 --> 00:08:22,600
10 automation accounts all meet these standards? You think some of them do, but

137
00:08:22,600 --> 00:08:25,600
you aren't sure about the others. You would have to audit them manually. Check each

138
00:08:25,600 --> 00:08:29,600
one and document what's broken. And then what? Next month someone adds a new

139
00:08:29,600 --> 00:08:33,600
account and forgets to enable diagnostics and now you're out of compliance again.

140
00:08:33,600 --> 00:08:36,600
This is where the real cost lives. It isn't in the effort of writing the scripts.

141
00:08:36,600 --> 00:08:39,600
The scripts work. The real cost is the invisible governance problem.

142
00:08:39,600 --> 00:08:43,600
You have infrastructure scattered across subscriptions with no single source of truth

143
00:08:43,600 --> 00:08:49,600
that says this is what should exist. You have no way to enforce standards

144
00:08:49,600 --> 00:08:53,600
automatically, no way to detect drift and no way to prove compliance. Every time

145
00:08:53,600 --> 00:08:57,600
in order to ask questions, you scramble to document what you have. Every time security

146
00:08:57,600 --> 00:09:01,600
reviews your work, you have to manually verify everything. Every time you

147
00:09:01,600 --> 00:09:05,600
onboard a new person, you have to walk them through undocumented dependencies.

148
00:09:05,600 --> 00:09:08,600
This isn't a problem with 50 scripts that work. This is a governance problem.

149
00:09:08,600 --> 00:09:11,600
This is an architecture problem. This is the point where scripting stops being

150
00:09:11,600 --> 00:09:16,600
enough. This is where infrastructure as code becomes non-negotiable. Enter infrastructure

151
00:09:16,600 --> 00:09:20,600
as code, the declarative shift. Infrastructure as code isn't a new concept.

152
00:09:20,600 --> 00:09:24,600
It's been around for years. Terraform has been doing this on AWS for a decade

153
00:09:24,600 --> 00:09:28,600
but using it for Microsoft 365 automation is relatively recent.

154
00:09:28,600 --> 00:09:31,600
This represents a fundamentally different way of thinking about what you're building.

155
00:09:31,600 --> 00:09:35,600
Let me explain the shift with a contrast. When you write a power shell script

156
00:09:35,600 --> 00:09:39,600
to deploy your automation platform, you're being imperative. You're giving orders.

157
00:09:39,600 --> 00:09:43,600
You say connect to Azure, create a resource group, create a storage account in that resource group,

158
00:09:43,600 --> 00:09:48,600
create a managed identity, wait for it to propagate, assign our back permissions to that identity,

159
00:09:48,600 --> 00:09:53,600
create a key vault, configure soft delete on the key vault, add access policies, create a function app,

160
00:09:53,600 --> 00:09:57,600
connect the function app to the storage account, enable monitoring, create a log analytics workspace,

161
00:09:57,600 --> 00:10:01,600
configure diagnostic settings to send logs to the workspace. Each line is a step,

162
00:10:01,600 --> 00:10:06,600
each step depends on the one before it. The order matters if you run step three before step two.

163
00:10:06,600 --> 00:10:12,600
It fails. If step five times out, step six through 12 might fail silently and you own all of that complexity.

164
00:10:12,600 --> 00:10:15,600
Now imagine a different model. You write a document that says,

165
00:10:15,600 --> 00:10:20,600
I want a function app environment that includes a storage account, a managed identity with storage access,

166
00:10:20,600 --> 00:10:24,600
a key vault with soft delete enabled and diagnostic logging to log analytics.

167
00:10:24,600 --> 00:10:28,600
You don't say how to create these things or in what order, you don't say which

168
00:10:28,600 --> 00:10:32,600
our back roles to assign or when to assign them, you don't say how to wait for identity propagation

169
00:10:32,600 --> 00:10:37,600
or handle timing issues, you just say what should exist. That's the declarative model. That's bicep.

170
00:10:37,600 --> 00:10:42,600
When you submit a bicep file to Azure, the system figures out the order and the dependencies.

171
00:10:42,600 --> 00:10:48,600
It decides which steps can run in parallel and which have to wait. It even handles the timing for identity propagation.

172
00:10:48,600 --> 00:10:52,600
It manages the complexity so you don't have to, but here's the problem with the old way.

173
00:10:52,600 --> 00:10:56,600
It doesn't know the final state with bicep. If you run the same file twice,

174
00:10:56,600 --> 00:11:01,600
the second time it only changes what's different. If someone deletes the key vault through the portal and you run bicep again,

175
00:11:01,600 --> 00:11:04,600
it recreates the key vault because the declaration says it should exist.

176
00:11:04,600 --> 00:11:08,600
The system becomes the source of truth, not your memory, not your scripts,

177
00:11:08,600 --> 00:11:14,600
not your notes on what was deployed and when, the contract is simple. Bicep says, this is what should exist.

178
00:11:14,600 --> 00:11:18,600
Azure makes sure it exists, always. This might sound like a small shift.

179
00:11:18,600 --> 00:11:23,600
It's not. It changes everything about how you think about infrastructure. With PowerShell, you're writing a procedure.

180
00:11:23,600 --> 00:11:27,600
Do this, then do this, then do this. If the procedure breaks halfway through,

181
00:11:27,600 --> 00:11:32,600
you have a half-built environment and you have to troubleshoot. You have to figure out what ran and what didn't.

182
00:11:32,600 --> 00:11:36,600
You have to decide whether to clean up and start over or try to fix it from the current state.

183
00:11:36,600 --> 00:11:44,600
With bicep, you're writing a specification. This is what should exist. If a deployment fails, you fix the definition and deploy again.

184
00:11:44,600 --> 00:11:49,600
The system will figure out what's already there and what needs to change. You're not managing a procedure.

185
00:11:49,600 --> 00:11:54,600
You're maintaining a description of desired state. Think about the implications for your 50 scripts.

186
00:11:54,600 --> 00:11:59,600
If you converted them to bicep, every piece of infrastructure would be declared in version control.

187
00:11:59,600 --> 00:12:03,600
Every change would be tracked in Git. Every deployment would follow the same pattern.

188
00:12:03,600 --> 00:12:08,600
Version control contains the truth and deployment brings reality into alignment with that truth.

189
00:12:08,600 --> 00:12:13,600
You want to rebuild your automation platform in a different subscription? Run the same bicep against a new subscription.

190
00:12:13,600 --> 00:12:18,600
It works. You want to prove compliance? Check the bicep file. It shows exactly what should exist,

191
00:12:18,600 --> 00:12:22,600
what permissions should be granted, and what monitoring should be in place. This is the shift.

192
00:12:22,600 --> 00:12:25,600
From how do I make this happen to? What should exist?

193
00:12:25,600 --> 00:12:28,600
And it solves the governance problem that PowerShell alone can't solve.

194
00:12:28,600 --> 00:12:35,600
Bicep isn't just a language, it's a mindset. Bicep is Azure's domain-specific language for defining infrastructure.

195
00:12:35,600 --> 00:12:39,600
When you hear that, you might think it's just another tool, like PowerShell, but for deployments.

196
00:12:39,600 --> 00:12:43,600
That misses the point entirely. Bicep is a language, yes. But more importantly,

197
00:12:43,600 --> 00:12:47,600
it represents a fundamentally different way of thinking about the systems you build.

198
00:12:47,600 --> 00:12:56,600
Here's what bicep does mechanically. You write files that describe resources, function apps, key vaults, storage accounts, networks, policies, anything that exists in Azure.

199
00:12:56,600 --> 00:13:00,600
You declare what you want. Bicep compiles those files into ARM templates.

200
00:13:00,600 --> 00:13:03,600
The format that Azure resource manager actually understands.

201
00:13:03,600 --> 00:13:06,600
But the language you write in is simpler than ARM Jason. It reads like a conversation.

202
00:13:06,600 --> 00:13:12,600
It reads like you're talking to someone telling them what infrastructure should exist. That simplicity matters.

203
00:13:12,600 --> 00:13:16,600
But it's not the real shift. The real shift is the mindset that comes with it. The mindset is this.

204
00:13:16,600 --> 00:13:20,600
Infrastructure is code. Not we're automating infrastructure deployment.

205
00:13:20,600 --> 00:13:25,600
Not we're scripting resource creation. Infrastructure is code. That means it gets treated like code.

206
00:13:25,600 --> 00:13:32,600
It lives in Git repositories. It gets reviewed in pull requests. It gets version controlled with commit messages that explain why something changed.

207
00:13:32,600 --> 00:13:36,600
It gets branched. It gets tested before deployment. It gets reverted if something breaks.

208
00:13:36,600 --> 00:13:42,600
Code review standards apply to infrastructure changes the same way they apply to application code. Code goes in version control.

209
00:13:42,600 --> 00:13:45,600
Version control is the source of truth. This is the part that rewires how you operate.

210
00:13:45,600 --> 00:13:50,600
In the scripting world, the portal is often the source of truth. You check the portal to see what's deployed.

211
00:13:50,600 --> 00:13:56,600
You check the portal to see what permissions exist. You check the portal to see what's configured. Your scripts are tools that modify the portal state.

212
00:13:56,600 --> 00:14:01,600
But the portal itself is the actual system. In the infrastructure as code world, Git is the source of truth.

213
00:14:01,600 --> 00:14:05,600
Your bicep files describe what should exist. Git contains the history of changes.

214
00:14:05,600 --> 00:14:10,600
If you want to know what permissions a keyboard should have, you read the bicep file. Not the portal.

215
00:14:10,600 --> 00:14:14,600
If you want to know who changed something and when you check Git history, not Azure activity logs.

216
00:14:14,600 --> 00:14:22,600
If you want to know why something was configured a particular way, you read the commit message in Git. This changes everything about accountability and reproducibility.

217
00:14:22,600 --> 00:14:28,600
A bicep file is a contract. When you write a bicep file that says deploy a keyboard with these specific permissions,

218
00:14:28,600 --> 00:14:33,600
Soft delete enabled and diagnostic logging to this log analytics workspace. That becomes the contract.

219
00:14:33,600 --> 00:14:39,600
It says this is what should exist in Azure. Anyone who reads that file knows what the infrastructure should look like.

220
00:14:39,600 --> 00:14:47,600
Any tool that reads that file can verify where the reality matches the contract. Any person who wants to change something knows exactly where to make the change.

221
00:14:47,600 --> 00:14:54,600
In the bicep file, in Git, through a pull request with a commit message explaining why. This is radically different from PowerShell scripts.

222
00:14:54,600 --> 00:14:58,600
Where the script is a procedure, but the system state is whatever happens when you run the procedure,

223
00:14:58,600 --> 00:15:02,600
plus whatever manual changes people made afterward, the implication is profound.

224
00:15:02,600 --> 00:15:05,600
You can recreate your entire automation platform from a Git repository.

225
00:15:05,600 --> 00:15:11,600
Not from memory, not from documentation that might be outdated, not from reverse engineering, what's in the portal from Git.

226
00:15:11,600 --> 00:15:16,600
You clone the repository, you run the bicep, everything gets deployed exactly as it was before.

227
00:15:16,600 --> 00:15:22,600
Every permission, every configuration, every monitoring setting, that's not just a technical difference, it's a structural difference.

228
00:15:22,600 --> 00:15:28,600
It means your infrastructure is reproducible, it means your infrastructure is auditable, it means your infrastructure is defensible.

229
00:15:28,600 --> 00:15:33,600
It's the difference between operating a platform and managing a collection of resources.

230
00:15:33,600 --> 00:15:39,600
The Microsoft Graph Breakthrough, Identity as Infrastructure. Here is the moment where everything changes.

231
00:15:39,600 --> 00:15:44,600
In July of 2025, Microsoft Graph bicep support finally went generally available.

232
00:15:44,600 --> 00:15:49,600
This isn't just a marketing announcement or a minor update, it is a structural shift in how we work.

233
00:15:49,600 --> 00:15:54,600
Because of this change, Identity is no longer just something you script. Identity is now infrastructure.

234
00:15:54,600 --> 00:15:59,600
And here is why that matters so much. For years, Identity Management lived in a completely different world from your infrastructure.

235
00:15:59,600 --> 00:16:04,600
You used Azure bicep or Terraform to deploy resources like Function Apps and Storage Accounts.

236
00:16:04,600 --> 00:16:13,600
But when you needed to create EntraID groups or register applications, you switched tools, you used PowerShell, you used the portal, you used Graph APIs in a custom script.

237
00:16:13,600 --> 00:16:17,600
Identity was always an action, it was something you did, something you executed.

238
00:16:17,600 --> 00:16:22,600
Now, it is something you declare. Inside a bicep file, you can now define your EntraID groups and your applications.

239
00:16:22,600 --> 00:16:26,600
You can define your service principles and the relationships between them.

240
00:16:26,600 --> 00:16:31,600
You can do all of this in the exact same file where you define your Function app and your key vault.

241
00:16:31,600 --> 00:16:36,600
You write the code once, it lives in Git, it describes the state you want, then Azure makes sure that state actually exists.

242
00:16:36,600 --> 00:16:39,600
Think about what this does to your automation platform.

243
00:16:39,600 --> 00:16:43,600
Before this breakthrough, your Identity Management was a mess of disconnected pieces.

244
00:16:43,600 --> 00:16:49,600
You had one PowerShell script to create an application registration and a second script to create the service principle.

245
00:16:49,600 --> 00:16:55,600
You had a third script to assign Graph permissions, maybe you even had a manual step in the portal to click through conditional access policies.

246
00:16:55,600 --> 00:16:59,600
All these pieces work together, but they weren't connected in any real way.

247
00:16:59,600 --> 00:17:03,600
There was no single declaration that defined the identity structure for your platform.

248
00:17:03,600 --> 00:17:05,600
Now, it works differently.

249
00:17:05,600 --> 00:17:10,600
You write bicep code that tells the system to create an EntraID application and a service principle.

250
00:17:10,600 --> 00:17:14,600
You tell it to grant specific Graph permissions and add that principle to security groups.

251
00:17:14,600 --> 00:17:17,600
You configure every access setting in one single place.

252
00:17:17,600 --> 00:17:20,600
It is versioned, it is reviewable, it is reproducible.

253
00:17:20,600 --> 00:17:26,600
Let's look at a concrete example. Imagine you are setting up a new automation account that needs to manage users and groups.

254
00:17:26,600 --> 00:17:31,600
Your account needs specific permissions like user.readwrite.all and group.readwrite.all.

255
00:17:31,600 --> 00:17:36,600
In the old model, you would register the application and then navigate through the portal to consent to permissions.

256
00:17:36,600 --> 00:17:41,600
You might miss one and have to go back, you would create a secret and then run another script to store it in a key vault.

257
00:17:41,600 --> 00:17:43,600
With Graph bicep, you just declare it.

258
00:17:43,600 --> 00:17:48,600
The bicep file states exactly what permissions the application needs and then Azure handles the rest of the work.

259
00:17:48,600 --> 00:17:55,600
The application is created, the service principle is provisioned, the permissions are granted, the infrastructure reflects exactly what you wrote in your code.

260
00:17:55,600 --> 00:18:00,600
But here is the deeper problem this solves. Identity is the control plane for everything.

261
00:18:00,600 --> 00:18:07,600
In Microsoft 365, every single thing flows through identity. Access to SharePointsites is controlled by groups.

262
00:18:07,600 --> 00:18:12,600
Teams channels rely on EntraID membership, licensing and delegates are tied to your identity.

263
00:18:12,600 --> 00:18:16,600
Every governance control you have is at its core and identity control.

264
00:18:16,600 --> 00:18:20,600
For years, we made these identity decisions through manual steps and scattered scripts.

265
00:18:20,600 --> 00:18:25,600
They weren't governed like infrastructure, they weren't version controlled or auditable as a complete system.

266
00:18:25,600 --> 00:18:29,600
You had scripts for groups and portal settings for permissions, but they were never connected.

267
00:18:29,600 --> 00:18:34,600
There was no single source of truth for your identity model. Now there is. Identity is finally infrastructure.

268
00:18:34,600 --> 00:18:38,600
You can write bicep that defines your entire model from licensing groups to automation accounts.

269
00:18:38,600 --> 00:18:41,600
Everything is declared, everything is versioned, everything is auditable.

270
00:18:41,600 --> 00:18:46,600
This is the bridge between basic power shell automation and true platform engineering.

271
00:18:46,600 --> 00:18:53,600
Governance is no longer just about securing a server. It is about securing the identity structure and the infrastructure together as code.

272
00:18:53,600 --> 00:18:58,600
When identity becomes infrastructure, your entire platform finally becomes governable.

273
00:18:58,600 --> 00:19:03,600
The performance reality bicep versus power shell versus terraform. So far we have talked about structure and governance.

274
00:19:03,600 --> 00:19:07,600
We have looked at how bicep gives you a source of truth that power shell cannot match.

275
00:19:07,600 --> 00:19:11,600
But there is another part of this decision that matters just as much, speed.

276
00:19:11,600 --> 00:19:20,600
And on the topic of speed, the data is very clear. Throughout 2024 and 2025, researchers tracked how these tools perform when provisioning Azure infrastructure.

277
00:19:20,600 --> 00:19:25,600
The results were not subtle. Bicep is the fastest tool available and it consistently uses the fewest resources.

278
00:19:25,600 --> 00:19:31,600
That isn't a marketing claim, it is measured performance across real world deployments. Here is why that happens.

279
00:19:31,600 --> 00:19:36,600
When you submit a bicep file to Azure, the resource manager service handles all the orchestration.

280
00:19:36,600 --> 00:19:42,600
It understands resource dependencies natively. It knows which parts can deploy at the same time and which parts have to wait.

281
00:19:42,600 --> 00:19:46,600
It knows exactly how long to wait for identity to propagate. It was built for this.

282
00:19:46,600 --> 00:19:51,600
So it works fast. When you use power shell for that same infrastructure, you are doing all that orchestration yourself.

283
00:19:51,600 --> 00:19:55,600
You write the logic, you decide the order, you handle the weights and the retries.

284
00:19:55,600 --> 00:19:59,600
That gives you a lot of control, but it also means you own every single failure point.

285
00:19:59,600 --> 00:20:05,600
If your timing is off by one second, the script fails. If you forget to account for an asynchronous operation, things break silently.

286
00:20:05,600 --> 00:20:08,600
You are managing complexity that Azure would have handled for you.

287
00:20:08,600 --> 00:20:13,600
Terraform works differently than both of them. Terraform keeps an explicit state file to track what is happening.

288
00:20:13,600 --> 00:20:18,600
That file is powerful because it helps with drift detection, but managing it adds a lot of operational overhead.

289
00:20:18,600 --> 00:20:25,600
You have to secure it and share it across your team. For scenarios that only involve Azure, that extra work just isn't necessary.

290
00:20:25,600 --> 00:20:30,600
The practical result is simple. Bicep wins on speed, power shell gives you control, but forces you to manage the mess.

291
00:20:30,600 --> 00:20:40,600
Terraform offers sophisticated state management, but requires much more discipline to run. For most Microsoft 365 infrastructure, Bicep is the fastest and simplest path.

292
00:20:40,600 --> 00:20:46,600
That doesn't mean the other tools are wrong. It just means if you want to deploy quickly and reliably, Bicep is the most direct way to get there.

293
00:20:46,600 --> 00:20:53,600
There is also a second performance advantage that matters for your situation, as your releases new services and features constantly.

294
00:20:53,600 --> 00:21:02,600
When Microsoft adds a new resource type, Bicep supports it on day one. This is because Bicep compiles into ARM templates, and those templates always support every Azure resource that exists.

295
00:21:02,600 --> 00:21:08,600
There is no lag, there is no waiting for a provider update or dealing with a version mismatch. Power shell is different.

296
00:21:08,600 --> 00:21:16,600
Power shell uses modules that have to be updated separately from the platform. When a new service launches, the PowerShell team has to update the modules.

297
00:21:16,600 --> 00:21:21,600
It usually happens fast, but it is never immediate. There is always a delay. Terraform often has an even longer lag.

298
00:21:21,600 --> 00:21:28,600
It relies on a provider maintained by the Terraform team rather than Microsoft. New Azure services can take weeks or even months to show up there.

299
00:21:28,600 --> 00:21:36,600
If you need to use cutting edge features, Terraform can actually block your progress. This matters for Microsoft 365, because you are often working on the bleeding edge.

300
00:21:36,600 --> 00:21:43,600
You are deploying new conditional access features and governance tools the moment they launch. Bicep lets you use them immediately. PowerShell usually can.

301
00:21:43,600 --> 00:21:49,600
Terraform might make you wait. This is the practical argument for using Bicep in an organization centered on Microsoft 365.

302
00:21:49,600 --> 00:21:55,600
It isn't just about the code or the source control, it is about speed. It is about supporting new features the second they are available.

303
00:21:55,600 --> 00:22:01,600
It is about making sure your infrastructure can keep up with the platform. But speed only matters if the system is reliable.

304
00:22:01,600 --> 00:22:08,600
That is where the governance layer comes back in. Bicep gives you both. It is fast enough to let you iterate. And it is structured enough to let you govern.

305
00:22:08,600 --> 00:22:15,600
That is the combination that real platform engineering requires on the architecture that actually works Bicep plus PowerShell plus Graph.

306
00:22:15,600 --> 00:22:22,600
You need to understand one thing before you choose a tool or structure your platform. Bicep, PowerShell and Graph are not competitors. They aren't alternatives.

307
00:22:22,600 --> 00:22:30,600
They are layers of the same system when you stop seeing them as competing choices. And start seeing them as complementary parts. Everything becomes clearer.

308
00:22:30,600 --> 00:22:37,600
Let's look at what each layer actually does. Layer one is Bicep. Bicep's job is to deploy the infrastructure, the scaffolding, the foundation.

309
00:22:37,600 --> 00:22:45,600
When you write Bicep, you are declaring that a function app should exist, that a key vault should exist, and that a storage account should have specific settings.

310
00:22:45,600 --> 00:22:53,600
You are defining the shape of the system. The container that everything else runs inside of. Bicep doesn't run your business logic. It doesn't call APIs. It doesn't process data.

311
00:22:53,600 --> 00:23:01,600
Bicep simply says, here is the environment where those things will happen. It is the stage, not the actors. Layer two is PowerShell.

312
00:23:01,600 --> 00:23:13,600
PowerShell's job is to orchestrate the operations. It runs inside the infrastructure that Bicep built. When Bicep deploys a function app, PowerShell runs inside it. When Bicep creates a managed identity, PowerShell uses that identity to authenticate.

313
00:23:13,600 --> 00:23:20,600
When Bicep provisions a key vault, PowerShell pulls the secrets out. PowerShell handles the logic, the workflows, the decision trees.

314
00:23:20,600 --> 00:23:28,600
It's the actor on the stage that Bicep built. Layer three is Graph Graph is the data layer. It provides the information, the users, the groups, the policies.

315
00:23:28,600 --> 00:23:39,600
When PowerShell needs to know who is in a group, it asks Graph. When PowerShell needs to assign a license. It tells Graph to do it. Graph is the source of reality, the system of record for everything in Microsoft 365.

316
00:23:39,600 --> 00:23:54,600
So how does this look in the real world? Imagine you're building a reporting platform for user activity. Bicep creates the infrastructure. It declares the function app and the storage account where logs will go. It sets up the managed identity so the app can talk to storage. It provisions the key vault for your credentials.

317
00:23:54,600 --> 00:24:01,600
It even sets up the log analytics workspace for your monitoring. All of that is in Bicep. It's version controlled. It's reproducible.

318
00:24:01,600 --> 00:24:10,600
PowerShell runs the actual logic. It lives inside that function app Bicep made. It uses the identity Bicep provisioned. It grabs the secrets Bicep stored. Then it executes the workflow.

319
00:24:10,600 --> 00:24:16,600
Connecting to Graph to see who signed in yesterday. It checks for session details and access patterns. It decides if anything looks suspicious.

320
00:24:16,600 --> 00:24:28,600
It writes the report to the storage account Bicep created. That is PowerShell's job. Graph provides the actual data. It tells PowerShell which users exist and when they last logged in. It provides the APIs that PowerShell calls to get the facts.

321
00:24:28,600 --> 00:24:36,600
It's the authoritative source for the entire environment. This architecture works because each tool stays in its lane. Bicep doesn't try to be a scripting language.

322
00:24:36,600 --> 00:24:44,600
PowerShell doesn't try to define infrastructure. Graph doesn't try to be an orchestration engine. Each one does one job. Does it well? And hands off to the next layer.

323
00:24:44,600 --> 00:24:59,600
The result is a platform that is modular. You can change the PowerShell logic without touching Bicep. The infrastructure stays stable. You can update your infrastructure without rewriting your scripts. The logic stays intact. The platform is flexible because the layers are independent. This is the architecture that actually scales.

324
00:24:59,600 --> 00:25:10,600
Governance is code. The real win. Governance isn't just policy. Most people think of governance as a rulebook. A document that says what's allowed. A checklist someone looks at once a quarter. That's the wrong mental model.

325
00:25:10,600 --> 00:25:25,600
Real governance is a control plane. It's the set of guardrails that makes certain things impossible. And other things automatic. It's not about knowing the rules. It's about building a system where the rules enforce themselves. That's what Bicep actually enables when you declare infrastructure in Bicep. You aren't just saying what should exist.

326
00:25:25,600 --> 00:25:35,600
You're embedding governance into the definition itself. Let's look at an example. Your security team says every automation account must have diagnostic logging enabled. This isn't a suggestion. It's a requirement.

327
00:25:35,600 --> 00:25:49,600
Every account needs logs flowing to a central workspace for auditing in a world of manual scripts. You handle this with a policy document. You tell the team, you send an email, you hope people remember. Then you manually audit the environment every few months.

328
00:25:49,600 --> 00:25:59,600
You find the accounts that don't have logs. You open a ticket. You wait for a fix. Compliance is a constant battle. You're always checking, correcting and reminding in the Bicep world. You embed the requirement into the code.

329
00:25:59,600 --> 00:26:12,600
You create a Bicep module for automation accounts. That module automatically enables logging. It hard codes the destination workspace. There is no option to turn it off. There is no workaround. Every account deployed through that module is compliant by default.

330
00:26:12,600 --> 00:26:19,600
Full stop. Compliance isn't something you check for. Compliance is something the infrastructure enforces. This changes your relationship with your infrastructure.

331
00:26:19,600 --> 00:26:26,600
Governance stops being a set of rules people might follow. It becomes the structure of the system itself. It's not aspirational. It's mandatory.

332
00:26:26,600 --> 00:26:37,600
Think about naming conventions. You want automation accounts to start with AA and key vaults to start with KV. In a script world, you rely on memory. People forget.

333
00:26:37,600 --> 00:26:49,600
Resources break the pattern. You have to rename things or file tickets. In Bicep, you make the naming convention part of the logic. The module takes a purpose and an environment as parameters. It builds the name automatically.

334
00:26:49,600 --> 00:27:00,600
There is no way to deploy a resource with the wrong name because the name is generated by the code. Naming conventions aren't rules to remember. They are architecture decisions that cannot be violated. The same applies to everything.

335
00:27:00,600 --> 00:27:09,600
Tagging standards. Baking them into the module. Permissions. Define them once. Encryption. Network isolation. It all lives in the Bicep definition.

336
00:27:09,600 --> 00:27:26,600
Governance shifts from checking to defining before you spend time discovering what was wrong. Now you define what is right and compliance is built in. The shift is profound. It's not about making more rules. It's about eliminating the possibility of breaking them. This is where Bicep becomes the foundation for platform engineering.

337
00:27:26,600 --> 00:27:35,600
Because platform engineering is about making it easier to do the right thing than the wrong thing. It's about removing friction from the compliant path. Bicep is the tool that makes that possible.

338
00:27:35,600 --> 00:27:49,600
The Entra ID governance layer. Identity governance is the foundation of Microsoft 365. Everything flows through it. When you control identity. You control the entire platform. You decide who exists. You decide what groups they join. You decide which permissions they hold.

339
00:27:49,600 --> 00:27:58,600
And for the first time, Bicep lets you declare that identity model the same way you declare your infrastructure. Think about what identity governance actually looks like in your organization.

340
00:27:58,600 --> 00:28:19,600
You need security groups for licensing tiers. You need different groups for different subscription levels. You need application registrations for every third party tool that connects to your tenant. In the old model, this was all manual. You would write a power shell script to create a group. You would write another script to register an application. You would write a third script to assign permissions. Each script was independent. They created your identity structure.

341
00:28:19,600 --> 00:28:29,600
But there was no single contract. You had scripts and you had results, but you didn't have a source of truth. Now, Bicep lets you declare it. You write a template that defines the security group for your e5 licensing tier.

342
00:28:29,600 --> 00:28:40,600
You define the application registration for your automation platform. You create the service principle and granted specific graph permissions for user management. It all lives in one place. It is version controlled. It is reviewable.

343
00:28:40,600 --> 00:29:05,600
The benefit is that your identity model becomes repeatable. You can deploy it to multiple tenants and get the exact same result every time. You can audit the environment by reading code instead of clicking through the portal. If you need to change a permission, you submit a pull request. But here's the problem with how we used to work. Identity and infrastructure were separate concerns. Bicep handled the servers. While portal clicks handled the users, they happened in different workflows at different times by different people.

344
00:29:05,600 --> 00:29:20,600
Identity decisions were never recorded the same way infrastructure decisions were. They didn't go through the same governance process. That's where things change. Now, identity is part of the infrastructure definition when someone wants to change a group or a permission. That change goes through a pull request. It gets reviewed, it gets tracked.

345
00:29:20,600 --> 00:29:32,600
This matters because identity is where security actually lives. It's where you enforce compliance. It's where access control happens. When identity governance becomes code, your entire security posture becomes unified.

346
00:29:32,600 --> 00:29:55,600
Infrastructure changes go through review. Identity changes go through the same review. The audit trails are automatic. This is where platform engineering actually starts. Not with the infrastructure, but with identity as infrastructure. Because if you control the identity layer, you control what the platform can and can't do. You control which applications exist. You control what service principles are allowed to touch. All declared, all reviewed, all auditable.

347
00:29:55,600 --> 00:29:59,600
That is the foundation everything else builds on.

348
00:29:59,600 --> 00:30:23,600
Reusability through modules, building your platform. This is where we move from theory into practice. We've talked about what bicep is. Now we need to talk about the part that actually scales your platform. Modules, a power shell script is singular. You write it for one purpose, for one problem in one environment. You can copy and paste it. But each instance is fundamentally separate. Each one carries its own hard coded values and its own quirks. Bicep modules work differently.

349
00:30:23,600 --> 00:30:37,600
Module is a packaged piece of infrastructure. It's a template you can deploy once and use everywhere. You don't copy it. You use it. You deploy the same module to dev and production and you get identical results. You deploy it to five different workloads and you get five properly configured instances.

350
00:30:37,600 --> 00:30:55,600
Look at a concrete example. You are deploying automation workloads. Each one needs a function app to run the code. Each one needs a storage account for logs. Each one needs a managed identity and a key vault for secrets. In most organizations, you've built these manually or with separate scripts. Each one is configured slightly differently depending on who is at the keyboard that day.

351
00:30:55,600 --> 00:31:22,600
Imagine a single bicep module called standard automation workload. When you use it, you pass in a few parameters. The name, the environment, the monitoring workspace, the module handles everything else. It creates the function app with the right configuration. It sets up the storage account with the correct tags. It configures the managed identity and the key vault access policies. You deploy that module once and you have a production ready environment. You deploy it again for a different workload and you have another one. Same module, different parameters.

352
00:31:22,600 --> 00:31:40,600
The power isn't in the module itself. It's in the consistency. Every workload build from this module has the same structure. It has the same security posture. It has the same naming convention when something breaks. You know how to fix it because you fixed it the same way before. When you need to update a setting, you change the module and redeploy it everywhere. This is where building platforms becomes possible.

353
00:31:40,600 --> 00:32:07,600
You aren't reinventing the wheel for each deployment. You are assembling from proven building blocks. Maybe you spend two weeks designing the perfect architecture for your function apps. That knowledge doesn't disappear after the first project. It lives in the module. Every team that needs that pattern gets access to it. Every deployment benefits from the thought that went into the original design. Microsoft recognized this pattern and created Azure verified modules. These are modules that Microsoft has written and tested for you. They cover the common patterns.

354
00:32:07,600 --> 00:32:34,600
Like a secure key vault or a hardened function app. When you use a verified module, you are getting architecture decisions made by specialists. You are getting code that has been validated across hundreds of organizations. You aren't starting from scratch. And this goes one level deeper. When you build modules for your own organization, you are building organizational knowledge. You are capturing decisions. You are making it. So the way your company does things isn't dependent on who is in the office. It's encoded in the modules. It's reproducible. It's teachable.

355
00:32:34,600 --> 00:32:51,600
A new engineer can deploy your entire stack just by combining your proven modules. This is platform engineering, not starting from zero each time, but building from consistent reusable pieces. Each module does one thing well. Together, they compose into complete systems. Version control, the source of truth.

356
00:32:51,600 --> 00:32:58,600
Version control is where the entire system becomes real. Not the portal, not your memory, not your documentation.

357
00:32:58,600 --> 00:33:15,600
Git. When you put power shell scripts in Git, you are tracking code. That's good. But when you put bicep in Git, you are tracking the specification of your entire infrastructure. Everything that should exist, every permission that should be granted, every monitoring, configuration and security setting that should be enforced. That's foundational.

358
00:33:15,600 --> 00:33:26,600
Because here is what changes. Your infrastructure becomes auditable at a granular level. In the old model, if someone modified a key vault permission, you had to go hunting. You'd click through the portal and check access control settings hoping to find a clue.

359
00:33:26,600 --> 00:33:37,600
Now, you just look at Git history. You see exactly when it changed. You see who did it. You see the commit message explaining why you see the pull request where the change was reviewed and approved. The entire chain of custody is just there.

360
00:33:37,600 --> 00:33:55,600
Before Git is truth, you had to ask questions. Who changed this? When did they do it? Why was this decision made? The portal doesn't answer those questions. As your activity logs might tell you that something changed, but they don't tell you the reasoning. They don't tell you if it was intentional or a mistake. They don't tell you who signed off on it. With bicep in Git, all of that is documented by default.

361
00:33:55,600 --> 00:34:08,600
Every change goes through a pull request. Every change has a commit message. Every change is part of the permanent record. The reasoning is documented. The reviewer is documented and the approval is documented. This matters for compliance more than anything else.

362
00:34:08,600 --> 00:34:18,600
Compliance auditors ask hard questions. They want to know what's deployed and who configured it. They want to see that configurations match your standards. They want proof that changes are reviewed before they ever touch production.

363
00:34:18,600 --> 00:34:28,600
With scripts in the portal, you scramble to find answers. You dig through logs, you interview people to understand decisions made months ago. You hope someone remembers, you hope documentation was kept. It's chaotic.

364
00:34:28,600 --> 00:34:40,600
With bicep in Git, you just hand over the repository. Here is everything that should exist. Here is when each piece was added. Here is who added it and why. Here is who reviewed it. It's all there. Compliance becomes documentation, not an investigation.

365
00:34:40,600 --> 00:34:49,600
The reversibility is just as important. Mistakes happen. Someone commits a bicep change that accidentally disables monitoring on every automation account in the tenant. That's a dangerous decision.

366
00:34:49,600 --> 00:34:57,600
With PowerShell scripts, you have to manually restore monitoring to each account or find the script that broke it and hope you can reverse it safely. It's manual, it's error-prone.

367
00:34:57,600 --> 00:35:06,600
With bicep in Git, you revert the commit. Done. Git knows exactly what change, so it applies the opposite change. Monitoring gets reenabled on everything that shouldn't have been touched.

368
00:35:06,600 --> 00:35:16,600
No manual steps, no uncertainty, no risk of only partially fixing the problem. This is why bicep in Git changes your operational model. It's not just about having code instead of portal clicks.

369
00:35:16,600 --> 00:35:26,600
It's about having an immutable record of every infrastructure decision. It's an audit trail that's generated automatically. It's a way to understand your system's history without having to interview people or guess at their intent.

370
00:35:26,600 --> 00:35:32,600
Your infrastructure stops being a mystery. It becomes a documented system. Everything that exists is there because it's declared in Git.

371
00:35:32,600 --> 00:35:42,600
Everything that changed is there because it's tracked in commits. Everything that's been approved is there because it went through a pull request. The system doesn't hide, it doesn't have secrets. It's transparent by design.

372
00:35:42,600 --> 00:35:52,600
And that transparency is what makes large-scale governance possible. The CICD pipeline, automation of automation, you have bicep files in Git. That's the foundation.

373
00:35:52,600 --> 00:35:59,600
But Git alone doesn't deploy anything. Git doesn't validate. Git doesn't prevent mistakes. Git doesn't enforce standards. A pipeline does.

374
00:35:59,600 --> 00:36:09,600
When you put power shell in a pipeline, the pipeline just runs scripts. It executes commands in order and deploys things. That's useful, but the pipeline itself doesn't understand what's being deployed.

375
00:36:09,600 --> 00:36:24,600
It doesn't know if the configuration makes sense or if it violates your standards. It just runs the script. When you put bicep in a pipeline, the pipeline becomes a governance enforcement point. It doesn't just execute, it validates, it tests, it previews, it makes sure nothing bad reaches production. Here's how this actually works.

376
00:36:24,600 --> 00:36:33,600
Write a bicep file that declares infrastructure changes. Maybe you're updating a key vault to add a new access policy or you're configuring a function app with a new environment variable.

377
00:36:33,600 --> 00:36:49,600
You commit that bicep file to Git and immediately the pipeline kicks in. Step one is validation. The pipeline compiles your bicep to make sure the syntax is correct. It checks that all the resources you're referencing actually exist and verifies that your parameter values are valid. It lends the code against your organization standards.

378
00:36:49,600 --> 00:37:09,600
If any of this fails, the pipeline stops. The deployment doesn't move forward. The pull request is blocked. You have to fix the bicep and commit again. Step two is testing. Depending on how sophisticated you want to be, you might run the bicep against a test subscription. You actually deploy it to see if everything works. You check that resources are created correctly, permissions are granted and monitoring is configured properly.

379
00:37:09,600 --> 00:37:23,600
If tests fail, the pipeline stops again. The problem has to be fixed before you can proceed. Step three is the preview. This is where bicep shines in a way PowerShell can't match. When you deploy bicep, you can run what if mode first. This shows you exactly what will change before anything actually happens.

380
00:37:23,600 --> 00:37:32,600
You see what resources will be created, modified or deleted. The pipeline runs this automatically and shows the preview to the reviewers, so they understand the impact before they hit approve.

381
00:37:32,600 --> 00:37:44,600
Step four is approval. A human has to approve the deployment. This is an optional, a person or a group of people has to review the bicep changes and the what if output. They have to understand what's being changed and why. Only then does the deployment proceed.

382
00:37:44,600 --> 00:37:52,600
Before you might have deployed infrastructure manually on your own schedule. Now the system enforces that every single change goes through review every time.

383
00:37:52,600 --> 00:38:00,600
Step five is the actual deployment. After approval, the pipeline deploys the bicep to the environment. It uses the exact same bicep that was reviewed and approved.

384
00:38:00,600 --> 00:38:07,600
No surprises, no manual changes, no one deploying a different version than what was reviewed. The pipeline handles the deployment consistently.

385
00:38:07,600 --> 00:38:17,600
But here's what's powerful about this workflow. Your infrastructure can never drift without you knowing about it. Supposed someone manually deletes a key vault through the Azure portal. That's bad. That's configuration drift.

386
00:38:17,600 --> 00:38:22,600
In a manual environment, you might not notice for weeks and by then you've lost your audit trail.

387
00:38:22,600 --> 00:38:37,600
In a pipeline-based bicep environment, the next time anyone commits a change, the pipeline runs the what if. The what if shows that the key vault will be recreated. It's immediately visible. It's immediately obvious that something changed. The reviewer sees it. They ask what happened and the problem gets fixed.

388
00:38:37,600 --> 00:38:48,600
More than that, you can run the pipeline on a schedule. Every night at midnight, the pipeline runs the bicep against your environment in what if mode. If anything is different or if any drift has occurred, the pipeline creates a report.

389
00:38:48,600 --> 00:38:56,600
It shows you exactly what drifted so you can fix it immediately. Your infrastructure never gets out of sync with your declarations. This is self-healing infrastructure.

390
00:38:56,600 --> 00:39:06,600
Not because it fixes itself automatically, but because every change is visible, every drift is detected, every problem surfaces immediately and gets corrected before it becomes a serious issue.

391
00:39:06,600 --> 00:39:15,600
This is where your platform stops being a collection of manual decisions and becomes an automated system. The migration path. From scripts to infrastructure.

392
00:39:15,600 --> 00:39:23,600
Everyone asks the same question when they stand at this threshold. They want to know if they have to throw away everything they've built with PowerShell. The answer is no, not even close.

393
00:39:23,600 --> 00:39:32,600
Moving from scripts to infrastructure isn't about replacement. It's about elevation. You keep your PowerShell, you keep your investment in automation and you keep the logic that actually works.

394
00:39:32,600 --> 00:39:45,600
What you're doing is adding an infrastructure layer on top to make everything governable, reproducible and scalable. The model is simple. You've been building on a foundation of loose sand, it held the house up and the house worked fine. But now you're pouring concrete underneath it.

395
00:39:45,600 --> 00:39:57,600
You aren't demolishing the building. You're just strengthening the base so the structure can last. So you can add more rooms and so the whole thing stays stable for whatever you build next. The migration follows a clear sequence. It isn't complicated, but the order matters.

396
00:39:57,600 --> 00:40:10,600
Start with step one. Identify what actually exists. This is the audit phase. You need to look at your Azure subscriptions and see which automation accounts are deployed, which function apps are running and where your storage accounts and key vaults are hiding.

397
00:40:10,600 --> 00:40:23,600
List them out. Understand their purpose. You have to document which script or process created each piece of infrastructure before you can move forward. It takes time, but it's necessary because you can't declare infrastructure in bicep if you don't know what's already there.

398
00:40:23,600 --> 00:40:35,600
While you're doing this audit, you'll probably find something unsettling. You'll find infrastructure that nobody remembers creating. Maybe it's a storage account from three years ago that nobody uses or a logic app that was deployed for a test and never removed.

399
00:40:35,600 --> 00:40:46,600
You might even find duplicate function apps because someone thought the original was gone when it wasn't. This is just the reality of the scripting phase. Things get created, some get used and some get forgotten. The audit brings it all into the light.

400
00:40:46,600 --> 00:40:59,600
Once you know what exists, move to step two. Write bicep for the foundation. Start with the core infrastructure that everything else depends on. This means the key vault where secrets live, the function app that runs your primary automation and the storage account for your logs.

401
00:40:59,600 --> 00:41:10,600
Don't try to move everything to bicep immediately. Focus on the foundation pieces that form the base of your platform. Write clean bicep for those, test them and make sure they deploy correctly. This becomes your core infrastructure definition.

402
00:41:10,600 --> 00:41:31,600
Step three is the big one. Don't try to move your operational logic to bicep. Keep power shell for what power shell is good at. Use it for graph API calls. Use a provisioning logic, reporting workflows and conditional business logic. Power shell stays. It runs inside the infrastructure that bicep deployed. It uses the managed identity that bicep provisioned and it pulls secrets from the key vault that bicep created.

403
00:41:31,600 --> 00:41:46,600
The logic itself stays in power shell because that's where it belongs. Step four is validation. Deploy your bicep to a test subscription and let it build the environment from scratch. Then run your power shell against it. The script should run inside the function app, retrieve it secrets and write it's logs just like before.

404
00:41:46,600 --> 00:41:59,600
Does everything work? Does power shell behave the same way it did when you built the infrastructure manually? It should. The infrastructure changed, but the operational logic shouldn't care as long as the resources exist. Once you've validated that the combination works, you can migrate at your own pace.

405
00:41:59,600 --> 00:42:15,600
Some teams do everything at once, but most do it gradually. They move their core automation infrastructure to bicep while keeping the operational scripts running. Over time they build out bicep modules for different patterns and standardize the new approach. Eventually they retire the old deployment scripts because they simply aren't needed anymore.

406
00:42:15,600 --> 00:42:25,600
But here's the problem people anticipate. They think they're losing flexibility. In reality, you're surrounding power shell with governance. You're defining the infrastructure layer that power shell runs on top of.

407
00:42:25,600 --> 00:42:33,600
You're making your entire platform reproducible and auditable while keeping the operational freedom that power shell provides. That's the shift, not replacement.

408
00:42:33,600 --> 00:42:40,600
Addition, real-world blueprint, the graph automation platform. Let's stop being abstract. Let's build something you probably need right now.

409
00:42:40,600 --> 00:42:49,600
Imagine you're in charge of automating user provisioning, license assignments and audit reporting for a Microsoft 365 environment. It's a real workload that needs to run reliably and scale.

410
00:42:49,600 --> 00:43:00,600
It has to be auditable and it needs to work exactly the same way in dev as it does in production. Here is what that platform actually requires. You need a function app to execute the logic on a schedule and a storage account to log activity.

411
00:43:00,600 --> 00:43:10,600
You need a managed identity so the app can talk to graph without storing passwords and a key vault to hold your connection strings. Then you need a log analytics workspace and application insights for monitoring.

412
00:43:10,600 --> 00:43:17,600
All these pieces have to exist. They have to be configured correctly and they have to work together. Now let's look at how you build this two different ways.

413
00:43:17,600 --> 00:43:27,600
In the PowerShell approach, you write a script to create the function app and run it manually. Then you write another script for the storage account, another for the resource group and you configure the managed identity separately.

414
00:43:27,600 --> 00:43:31,600
You create the key vault, manually set up access policies and then move on to the logging tools.

415
00:43:31,600 --> 00:43:39,600
You run these scripts in order, hoping you remember the right sequence. Some run fine, others fail. And you spend your afternoon debugging parameters and re-running code.

416
00:43:39,600 --> 00:43:49,600
Eventually everything exists, you document what you did and hope nobody asks you to do it again. Then you want to deploy the same platform to production, you copy all your scripts, modify the names and change the parameters.

417
00:43:49,600 --> 00:43:54,600
You hope you didn't miss anything, but some configurations might be different because you made a different choice this time.

418
00:43:54,600 --> 00:44:01,600
Months later, you need a third environment. You copy the scripts again, modify them again and now you have three slightly different versions of the same platform.

419
00:44:01,600 --> 00:44:12,600
Each deployment was a manual process and each one has small variations. This is the reality of script-based infrastructure. It works and it gets the job done, but it doesn't scale. It doesn't stay consistent or documented.

420
00:44:12,600 --> 00:44:19,600
Each deployment is just a one-off manual event. Now look at the bicep approach. You write one bicep file that declares exactly what should exist.

421
00:44:19,600 --> 00:44:28,600
The function app, the storage account, the managed identity and the key vault are all defined in one place. You connect them through logical references, validate the file and commit it to Git.

422
00:44:28,600 --> 00:44:37,600
You deploy it to Dev, three minutes later everything exists and is configured correctly. Now you want production, you don't copy the bicep, you deploy the exact same file using different parameters.

423
00:44:37,600 --> 00:44:49,600
The Dev environment might use a Dev suffix while production uses prod and the resource sizes might be different, but the structure is identical. Same bicep, different parameters, three minutes later your production environment is ready.

424
00:44:49,600 --> 00:44:54,600
You need a third environment for testing, same bicep, test parameters, three minutes done.

425
00:44:54,600 --> 00:45:02,600
Now imagine six months from now when something needs to change. Maybe the function app needs a new environment variable or the logs need a longer retention period.

426
00:45:02,600 --> 00:45:11,600
You update the bicep once, validate it and commit the change to Git with a clear note explaining why. The pull request gets reviewed and then you deploy it to all three environments automatically.

427
00:45:11,600 --> 00:45:15,600
The change is consistent, it's traceable and it's reversible if things go wrong.

428
00:45:15,600 --> 00:45:23,600
What would have been three separate manual chores now happens in a unified way, the impact compounds. What took weeks to deploy manually now takes minutes with bicep.

429
00:45:23,600 --> 00:45:29,600
What was fragile and inconsistent becomes stable and repeatable. What was undocumented is now version controlled and auditable.

430
00:45:29,600 --> 00:45:38,600
The platform scales from one environment to five without the operational burden multiplying. That's the real difference. It isn't just about speed, it's about consistency, governance and repeatability.

431
00:45:38,600 --> 00:45:42,600
This is what the platform engineering layer actually enables.

432
00:45:42,600 --> 00:45:49,600
The governance baseline, what bicep actually enforces. Governance stops being a theory the moment you bake it into your infrastructure.

433
00:45:49,600 --> 00:45:57,600
Most people talk about governance like it's a control plane, a way to make rules that are impossible to break, but we need to look at what that actually looks like when you're working.

434
00:45:57,600 --> 00:46:04,600
There is a massive gap between having a naming convention written in a PDF and having a naming convention enforced by the system itself.

435
00:46:04,600 --> 00:46:08,600
Bicep handles four main areas of governance for M365 automation.

436
00:46:08,600 --> 00:46:14,600
Naming, tagging, diagnostics are back. These are the four pillars where governance finally becomes real.

437
00:46:14,600 --> 00:46:23,600
What about naming first? Your company probably has a rule for this already. Maybe your automation accounts have to start with a specific prefix followed by the environment name.

438
00:46:23,600 --> 00:46:29,600
You have these rules in an email or a document somewhere and you've probably spent hours renaming resources because someone forgot to follow them.

439
00:46:29,600 --> 00:46:34,600
That is the old model. It relies on everyone remembering the rules every single time in bicep.

440
00:46:34,600 --> 00:46:43,600
The naming convention is just part of the module logic. When someone deploys an automation account using your standard module, they just provide the purpose and the environment as simple inputs.

441
00:46:43,600 --> 00:46:47,600
It also takes those strings, combines them with the right prefix and creates the name automatically.

442
00:46:47,600 --> 00:46:54,600
The person doing the work doesn't even make a decision about the name. Compliance isn't a choice they make. It's just what happens. Tagging works the same way.

443
00:46:54,600 --> 00:46:59,600
Every resource needs a business unit, a cost center, and an owner for billing and compliance reasons.

444
00:46:59,600 --> 00:47:06,600
In a manual world, you just hope people remember to add them. Usually they don't, then you have to run audits, find the missing tags, and create tickets to fix them.

445
00:47:06,600 --> 00:47:17,600
It's a constant uphill battle with bicep. Tagging is baked into the foundation. Every module applies the required organizational tags to every resource it touches. The user provides the cost center as a parameter.

446
00:47:17,600 --> 00:47:23,600
And the module handles the rest. There are no exceptions and no forgotten tags. Every resource is born compliant from day one.

447
00:47:23,600 --> 00:47:30,600
Then you have diagnostic settings. Your organization likely requires logs for auditing and security. You could write a policy to check for this.

448
00:47:30,600 --> 00:47:37,600
But policies are reactive. They tell you that you broke the rule after the resource is already live. With bicep, the diagnostic settings are inside the template.

449
00:47:37,600 --> 00:47:45,600
Your module for function apps configures logging by default. So there is no way to skip it. Every app you deploy starts sending logs to your workspace immediately.

450
00:47:45,600 --> 00:47:53,600
The same logic applies to RBIAC. Access control is the most sensitive part of the stack. Your automation accounts need specific permissions based on the principle of least privilege.

451
00:47:53,600 --> 00:48:02,600
Instead of hoping your team understands the nuances of graph permissions, your bicep module manages it, the module creates the identity, assigns the roles, and grants the permissions.

452
00:48:02,600 --> 00:48:12,600
The person deploying the code doesn't need to be an RBIAC expert because the permissions are correct by design. This changes everything for your operations. Imagine an auditor asks for a report on your infrastructure.

453
00:48:12,600 --> 00:48:22,600
They want to know what's out there, who has access, and if it's being logged in the old world of scripting, you'd be scrambling. You'd be clicking through the portal and filling out spreadsheets, hoping you didn't miss a single resource.

454
00:48:22,600 --> 00:48:29,600
With bicep, you just show them the repository. You point to your standard module and explain that every automation account comes from this single source.

455
00:48:29,600 --> 00:48:36,600
This is your governance baseline. Every instance has the same naming, the same tags, and the same logging. Nothing deviates because the module won't allow it to.

456
00:48:36,600 --> 00:48:43,600
This is a profound shift in how you work. Compliance moves from something you should do to something the system forces you to do.

457
00:48:43,600 --> 00:48:49,600
You move away from hope and towards certainty. You stop auditing for mistakes and start preventing them from ever happening.

458
00:48:49,600 --> 00:48:59,600
Your audit results don't get better because you got better at remembering rules. They get better because the rules are now a physical part of the system. Compliance becomes a feature of your infrastructure, not a chore you have to manage.

459
00:48:59,600 --> 00:49:07,600
The career ceiling. Why platform engineers earn more? We need to talk about money because the market is sending a very clear signal about where the value is.

460
00:49:07,600 --> 00:49:16,600
Platform engineers are consistently earning 20% to 40% more than traditional DevOps engineers. This isn't a fluke or a one-time trend. It's happening across every industry and every country.

461
00:49:16,600 --> 00:49:22,600
The market is telling us that organizations will pay a premium for people who build systems instead of just finishing tasks.

462
00:49:22,600 --> 00:49:28,600
The reason for this comes down to impact. A DevOps engineer focuses on automation. They might write a script to set up a server.

463
00:49:28,600 --> 00:49:35,600
Which saves time and prevents a few manual errors. That is definitely valuable. But the value is limited. That script does one specific thing for one specific process.

464
00:49:35,600 --> 00:49:44,600
A platform engineer builds the engine. They design a system that allows 50 different teams to set up their own servers consistently. They create the standards that scale across the entire company.

465
00:49:44,600 --> 00:49:49,600
The value isn't found in a single script. It's found in the infrastructure that makes every other script better.

466
00:49:49,600 --> 00:49:57,600
The impact isn't just one team moving faster. It's the entire organization shifting to a new level of reliability. That is why the pay gap is so large.

467
00:49:57,600 --> 00:50:04,600
It isn't that platform engineers are smarter. It's that their work is a force multiplier. When a platform engineer fixes a pipeline, everyone gets faster.

468
00:50:04,600 --> 00:50:10,600
When they automate governance, every future deployment is automatically cleaner. There work scales in a way that a single script never can.

469
00:50:10,600 --> 00:50:20,600
The math is pretty easy to follow. If you improve one script, you might save 10 hours a week for one small team. But if you build a platform that changes how 50 teams work, you are saving thousands of hours every single year.

470
00:50:20,600 --> 00:50:27,600
The economic value of that work is on a completely different scale. Companies know this. And they've structured their pay scales to reflect it.

471
00:50:27,600 --> 00:50:36,600
Senior roles in cloud engineering are going to the people who think in platforms. At the biggest tech companies, senior platform roles pay between 300,000 and $575,000.

472
00:50:36,600 --> 00:50:47,600
At the staff and principal levels, those numbers can climb to 900,000 or more. These aren't lottery salaries. They are the standard rates for people who solve systemic problems. This is where bicep comes in for your career.

473
00:50:47,600 --> 00:50:55,600
Bicep is the language of this transition. When you move away from PowerShell and start using bicep, you are shifting from, "How do I do this to? What should exist?"

474
00:50:55,600 --> 00:51:00,600
You aren't just learning a new way to type. You are building the mental model that commands those higher salaries.

475
00:51:00,600 --> 00:51:09,600
Bicep acts as a credential for systems thinking it tells the market that you understand infrastructure as code. And that you value version control as the source of truth.

476
00:51:09,600 --> 00:51:17,600
It shows you know how to build reusable modules and declarative governance. When you master bicep, you have mastered the exact discipline that companies are desperate to pay for.

477
00:51:17,600 --> 00:51:20,600
This isn't just about being cynical, it's about being practical.

478
00:51:20,600 --> 00:51:27,600
The market pays for leverage. A PowerShell script only has as much leverage as the person running it. A bicep module has leverage across the entire enterprise.

479
00:51:27,600 --> 00:51:35,600
The return on investment for a platform engineer is simply higher for the business. Tasks that used to take weeks of manual effort now take minutes because of bicep.

480
00:51:35,600 --> 00:51:43,600
Fragile processes that used to break are now stable and repeatable. Specialized knowledge that lived in one person's head is now documented in the code itself.

481
00:51:43,600 --> 00:51:51,600
These aren't just nice improvements. They are competitive advantages for the company. Moving from PowerShell to bicep is a career defining move.

482
00:51:51,600 --> 00:51:59,600
It's the difference between being useful to one team and being essential to the whole organization. It's the shift from focusing on tasks to focusing on systems.

483
00:51:59,600 --> 00:52:05,600
The market rewards that shift with better pay, better opportunities and a much better long term trajectory. That isn't a coincidence.

484
00:52:05,600 --> 00:52:08,600
It's just the market recognizing where the real value lives.

485
00:52:08,600 --> 00:52:19,600
The skill gap. Why bicep expertise is rare. Most IT professionals know PowerShell. It is everywhere. You learned it because you had to and you probably started because you needed to automate a specific task.

486
00:52:19,600 --> 00:52:29,600
You looked up the syntax, you wrote the script and you solved the problem. That is the dominant path for most people in this industry and it is exactly why PowerShell is the default language for almost everyone.

487
00:52:29,600 --> 00:52:36,600
Bicep expertise is different. It is rare. The reason isn't that bicep is harder to learn in a technical sense because in reality it isn't.

488
00:52:36,600 --> 00:52:42,600
The syntax is cleaner than PowerShell. The language is simpler and you can pick up the basics over a single weekend.

489
00:52:42,600 --> 00:52:52,600
The problem isn't learning the language. The problem is learning the thinking. PowerShell is a tool for finishing tasks. You approach it with a specific problem in mind, like creating a user or assigning a license.

490
00:52:52,600 --> 00:52:56,600
You write a script to generate a report and then you move on to the next thing.

491
00:52:56,600 --> 00:53:05,600
The learning path is problem-driven meaning you encounter a hurdle, you clear it and you continue. That approach works for most people which is why the barrier to entry stays low.

492
00:53:05,600 --> 00:53:14,600
The entry point is always a real immediate need. Bicep requires a different mental model. It isn't about solving today's problem but rather about defining how a system should exist.

493
00:53:14,600 --> 00:53:21,600
That is abstract, that is architecture. Most people don't approach technology from that angle because they are trained to focus on the task at hand.

494
00:53:21,600 --> 00:53:29,600
They aren't taught to think declaratively and they aren't exposed to infrastructure thinking early in their careers. They learn to fix problems, not to define systems.

495
00:53:29,600 --> 00:53:40,600
Transitioning from task thinking to systems thinking is difficult. It isn't a skill you pick up just because you have a bicep file to edit this afternoon. It is a model you have to adopt and it requires asking entirely different questions.

496
00:53:40,600 --> 00:53:48,600
Instead of asking how to provision a resource you ask what should exist in the first place. Instead of worrying about the sequence of operations you focus on the desired state.

497
00:53:48,600 --> 00:53:55,600
These aren't small shifts and they require rewiring how you approach every problem you face. This creates a massive supply problem.

498
00:53:55,600 --> 00:54:01,600
Organizations need platform engineers who think systemically about infrastructure and can build the abstractions that other teams depend on.

499
00:54:01,600 --> 00:54:07,600
But the supply of those people is limited because very few have made the jump from task automation to systems design.

500
00:54:07,600 --> 00:54:14,600
Most power shell experts stay in that task oriented mindset and while they are valuable they don't make the leap to the bicep mindset. The gap is only getting wider.

501
00:54:14,600 --> 00:54:23,600
More organizations are adopting infrastructure as code and more teams are hunting for platform engineers. The demand is accelerating but the supply of qualified people isn't keeping pace.

502
00:54:23,600 --> 00:54:32,600
That is the classic economic signal for a skill shortage. When demand exceeds supply prices rise and organizations are now paying huge premiums for real bicep expertise.

503
00:54:32,600 --> 00:54:40,600
If you make the transition now you aren't competing with everyone else who knows power shell. You are competing with a small percentage of people who have learned to think in systems.

504
00:54:40,600 --> 00:54:47,600
You are entering a market where demand exceeds supply and that is exactly the position you want to be in. But here is the reality check. This isn't a quick skill to acquire.

505
00:54:47,600 --> 00:54:55,600
You can't cram bicep syntax over a weekend and call yourself an expert because knowing the language doesn't give you platform engineering expertise. The value is in the thinking.

506
00:54:55,600 --> 00:55:02,600
It is an understanding how to design abstractions, how to handle governance at scale and how to build modules that work across different contexts.

507
00:55:02,600 --> 00:55:12,600
That takes time. It takes practice. It takes exposure to systems that are well designed and systems that are absolute disasters. It takes failure and the depths that comes from building real platforms instead of toy projects.

508
00:55:12,600 --> 00:55:22,600
The opportunity exists because most people simply won't invest that time. Most power shell experts will stay focused on their tasks and most people learning bicep will learn the syntax without ever touching the systems thinking.

509
00:55:22,600 --> 00:55:30,600
If you make the shift really make it you are ahead of the vast majority. You are joining a small group and the market is more than happy to pay for membership in that group.

510
00:55:30,600 --> 00:55:42,600
The AI angle, why bicep becomes more important? AI is going to write code. It isn't a maybe anymore. Large language models are already generating functional power shell and bicep and that capability is improving every single week.

511
00:55:42,600 --> 00:55:52,600
Within a year or maybe just a few months, AI will generate infrastructure code reliably on its scale. A lot of people think that is bad news for engineers. If AI can write the code, they wonder why we even need humans.

512
00:55:52,600 --> 00:56:11,600
It is a natural reaction to have but it misses what is actually happening. AI can generate code but it cannot decide where that code should run or what it should actually do. It doesn't know if the code aligns with your organization standards and it doesn't know what to do when the integration breaks. Those are code problems. Those are architecture problems, those are governance problems and those are the things that sit above the code.

513
00:56:11,600 --> 00:56:19,600
Bicep is exactly that layer. It doesn't describe how to do something but rather what should exist. It describes the constraints, the standards and the desired outcomes.

514
00:56:19,600 --> 00:56:28,600
Bicep is the specification that tells the AI where to operate and how to operate safely within your boundaries. Think about the practical reality you will face in the next few years.

515
00:56:28,600 --> 00:56:46,600
Right now if you tell an AI to write power shell that provisions users, it will write functional code. But where does that code run? Does it have access to the key vault? Are the permissions configured correctly? Is there a managed identity in place? These are all infrastructure questions that power shell doesn't answer. Power shell assumes the infrastructure already exists and if it doesn't, the script just fails.

516
00:56:46,600 --> 00:57:01,600
Now imagine the AI works against the bicep declaration. You tell the system what should exist including the function app, the key vault and the managed identity. When you ask the AI to write the power shell that runs inside that defined infrastructure, it suddenly has guardrails. It has a specification to work against.

517
00:57:01,600 --> 00:57:12,600
The code it generates is constrained by what you have declared in bicep. The shift is massive. It moves AI from a tool that generates code in isolation to a tool that generates code within your specific architecture.

518
00:57:12,600 --> 00:57:23,600
That is a completely different proposition and it is how you keep AI safe at scale. You don't stay safe by avoiding the tools but by defining the boundaries they operate within. This also changes what makes you irreplaceable.

519
00:57:23,600 --> 00:57:32,600
You aren't valuable because you can write power shell faster than a machine because you can't. The AI wins that race every time. You are irreplaceable because you understand systems.

520
00:57:32,600 --> 00:57:45,600
You can look at a business requirement and translate it into infrastructure declarations. You can define what should exist, how it integrates and how it is governed. That is bicep thinking, that is architecture, that is what machines can help with but cannot replace. The future workflow is clear.

521
00:57:45,600 --> 00:57:53,600
You decide what infrastructure should exist and you declare it in bicep. You commit that to Git and then describe the operational logic to an AI.

522
00:57:53,600 --> 00:58:06,600
The AI generates the power shell that runs on top of that infrastructure and you review it. You test it against the bicep defined environment, you approve it and you deploy it. The system works because the infrastructure was defined first and the boundaries were clear.

523
00:58:06,600 --> 00:58:18,600
This is why understanding bicep becomes more important in an AI world, not less. Bicep is how you maintain control. It is how you define what is possible and how you keep the system aligned with your standards even when parts of it are generated by machines.

524
00:58:18,600 --> 00:58:31,600
Organizations that understand this will move fast. Organizations that don't will end up with infrastructure they don't understand running on environments that weren't planned for it. That is chaos. And it is the exact opposite of what platform engineering is supposed to achieve.

525
00:58:31,600 --> 00:58:38,600
The barrier to being irreplaceable isn't code anymore. It is architecture. It is the ability to think systemically about infrastructure. It is bicep.

526
00:58:38,600 --> 00:58:50,600
Not because the language is hard to learn but because it represents the level of thinking that cannot be automated away. At least not for a very long time. The honest limitations, what bicep doesn't do. I need to be direct about what bicep isn't.

527
00:58:50,600 --> 00:59:04,600
There is a risk in everything we've discussed so far. You might finish this episode thinking bicep is a universal solution. That if you just move everything over, your infrastructure problems will dissolve. That isn't how it works. Bicep is powerful but it has real boundaries. The first boundary is scope.

528
00:59:04,600 --> 00:59:13,600
Bicep is Azure only. It deploys Azure resources and that's the end of the list. If your organization runs anything on AWS or on premises hardware, bicep won't touch it.

529
00:59:13,600 --> 00:59:26,600
If you need a unified tool that spans every cloud, bicep isn't the answer. Terraform is. Terraform understands AWS and GCP and Kubernetes along with dozens of other platforms. Bicep understands Azure and nothing else. That isn't a flaw. It's by design.

530
00:59:26,600 --> 00:59:38,600
Microsoft built bicep specifically to be optimized for Azure but it does mean you can't use it as a universal language if you operate across multiple clouds. The second boundary matters even more for m365 focused organizations.

531
00:59:38,600 --> 00:59:46,600
Bicep doesn't manage Microsoft 365 workload configuration. At least not directly. You can't use bicep to configure exchange online mailbox rules.

532
00:59:46,600 --> 00:59:56,600
You can't define teams policies or manage sharepoint site settings through a bicep file. Bicep deploys the infrastructure that supports those things. It handles the function app, the logging pipeline and the authentication layer.

533
00:59:56,600 --> 01:00:05,600
But the actual m365 workload configuration still requires power shell or graph or the admin portal. Understanding this prevents a specific category of mistakes.

534
01:00:05,600 --> 01:00:14,600
Someone new to infrastructure as code might wonder why they can't manage everything with one tool. The answer is that m365 isn't exposed through the Azure resource manager.

535
01:00:14,600 --> 01:00:25,600
Exchange online teams and sharepoint are SaaS services with their own APIs and control planes. They aren't arm resources. Bicep only touches what arm exposes so everything else requires different tools.

536
01:00:25,600 --> 01:00:38,600
The practical implication is that bicep becomes one layer of your platform. Not the only layer, your platform consists of bicep handling infrastructure while power shell handles operations and graph APIs provide the data. These tools are complimentary. They don't overlap.

537
01:00:38,600 --> 01:00:49,600
Accepting that boundary is part of professional systems thinking. There's a third limitation worth naming. Bicep doesn't replace existing m365 admin tools like the exchange or team's admin centers. Those tools exist for a reason.

538
01:00:49,600 --> 01:00:59,600
Suppose the full feature set of the services, which bicep doesn't do, bicep gives you the infrastructure substrate while the admin tools give you the service configuration. Both are necessary and neither replaces the other.

539
01:00:59,600 --> 01:01:10,600
The final limitation is less technical and more about your organization. Bicep requires a different operational model. It requires Git discipline, pull request reviews and pipeline validation.

540
01:01:10,600 --> 01:01:22,600
If your organization isn't ready for that, if people are used to making direct portal changes and documenting them later, bicep adoption will be harder. It's not impossible, but it's a shift. You aren't just adopting a new tool. You're changing how decisions get made and recorded.

541
01:01:22,600 --> 01:01:36,600
Understanding these boundaries is a sign of mature thinking. It means you aren't treating bicep as a silver bullet. You're thinking about architecture as layers and components, each with its own purpose. That's platform engineering thinking. Knowing what a tool can't do is just as important as knowing what it can.

542
01:01:36,600 --> 01:01:54,600
The bicep versus terraform decision and why it matters. At this point, someone always asks the obvious question, bicep sounds great. But what about terraform? Isn't terraform the industry standard? Should I just learn that instead? The answer requires some nuance. Both tools are legitimate and both solve real infrastructure problems. But they solve different problems.

543
01:01:54,600 --> 01:02:14,600
Understanding the difference is how you make the right choice for your specific situation. Terraform is multi-cloud. That is its defining characteristic. You write terraform and it can manage resources on AWS. Or you use the same structure to manage GCP. You use the same language and the same thinking across every cloud. For organizations that operate across multiple providers, terraform is the natural choice.

544
01:02:14,600 --> 01:02:30,600
It keeps your code consistent even as the underlying platforms change. That is valuable. If you're running workloads on AWS and Azure and GCP, terraform makes sense. Bicep is Azure native. It's designed for one cloud and optimized for one cloud. It compiles directly to ARM, which means it gets new features the same day as you releases them.

545
01:02:30,600 --> 01:02:42,600
It integrates with the Azure CLI and the portal in ways terraform simply can't. For organizations that are entirely in Azure, that native integration is a massive advantage. You aren't paying the cost of a multi-cloud abstraction when you don't actually need it.

546
01:02:42,600 --> 01:02:58,600
Now, let's look at how this works for M365 specifically. Most Microsoft 365 organizations are Azure only or heavily Azure primary. Your identity lives in Entra ID, your authentication runs through Azure AD and your automation runs on Azure functions. Microsoft 365 is tightly bound to Azure.

547
01:02:58,600 --> 01:03:19,600
When you're building infrastructure to support M365, you're almost always building in Azure. If that describes your situation. If you aren't managing AWS workloads or spanning multiple clouds, terraform introduces complexity you don't need. It adds abstraction and conceptual overhead. You gain a multi-cloud capability that you'll never actually use. Bicep by contrast is purpose-built for exactly what you're doing.

548
01:03:19,600 --> 01:03:29,600
The research on adoption supports this. Bicep is growing fastest in Azure only organizations. Companies that committed to Azure as their primary cloud are increasingly choosing bicep because it fits.

549
01:03:29,600 --> 01:03:40,600
It's simpler, it's faster and it requires less operational overhead. The cognitive load is lower because you aren't thinking in multi-cloud abstractions. That said, there are scenarios where terraform wins for M365 shops.

550
01:03:40,600 --> 01:03:54,600
If your organization runs parts of its infrastructure on AWS or if you have on-premises components that need to be managed as code, terraform becomes the right choice. You trade Azure native simplicity for multi-cloud consistency. That is a reasonable trade but it depends on your situation.

551
01:03:54,600 --> 01:04:09,600
Here is the framework that should guide your decision. Ask yourself three questions. First, do you operate across multiple clouds today? Not hypothetically, but actually right now. If the answer is no, bicep is more efficient. Second, is there any realistic possibility you'll operate across multiple clouds in the next few months?

552
01:04:09,600 --> 01:04:22,600
This is harder to answer but it matters for your learning investment. If your organization has committed to Azure as its strategic platform, the probability is low. If you're deliberately pursuing a multi-cloud strategy, the probability is high.

553
01:04:22,600 --> 01:04:33,600
Third, do you already have terraform expertise in your organization? If you have teams that already know HCL and understand terraform workflows, extending that to Azure might be simpler than introducing a new tool.

554
01:04:33,600 --> 01:04:57,600
Consistency across your tools might outweigh the advantages of biceps integration. For most M365 shops, the answer to those first two questions points toward bicep. You operate in Azure, you're planning to stay in Azure and Azure is your platform. Bicep was built for you. The practical truth is this. Don't choose your tool because it's trendy or because other people use it. Choose it based on your actual cloud strategy. If your Azure only building bicep expertise is more efficient than learning terraform.

555
01:04:57,600 --> 01:05:07,600
You'll move faster, you'll have fewer abstractions to manage and you'll integrate more cleanly with your existing tooling. I'm not saying terraform is wrong, I'm saying you should choose based on your reality, not on assumptions about what you should be using.

556
01:05:07,600 --> 01:05:21,600
The transition starts now. Your first steps. You're standing at the threshold. You understand why bicep matters. You've seen the architecture, you know the career implications. But now the question is, what do you actually do Monday morning when you sit down at your desk?

557
01:05:21,600 --> 01:05:30,600
The answer is simpler than you think, don't try to migrate everything at once. Don't try to redesign your entire automation platform overnight. Start small, build momentum, learn by doing.

558
01:05:30,600 --> 01:05:39,600
Step one is changing how you approach a problem. Right now when you see a task, you ask, how do I do this? You write a script that performs the action. That's task thinking.

559
01:05:39,600 --> 01:05:46,600
What you need to practice is state thinking. Instead of asking, how do I create this resource? You ask, what should exist when I'm done?

560
01:05:46,600 --> 01:05:53,600
It's a subtle shift, but it's fundamental. It rewires your brain and once you start thinking this way, bicep becomes the natural tool to express it.

561
01:05:53,600 --> 01:06:00,600
Step two is writing your first bicep file. Don't start with something ambitious, start dead simple. Deploy a key vault. That's it.

562
01:06:00,600 --> 01:06:05,600
Right maybe 15 lines of bicep. Create a resource group, create a key vault with a couple of basic settings.

563
01:06:05,600 --> 01:06:13,600
Deploy it, see it work. You'll learn more from deploying one simple resource than from reading 10 tutorials. The goal isn't to build production infrastructure yet.

564
01:06:13,600 --> 01:06:18,600
The goal is to feel how bicep works. You need to see the compilation process. You need to watch the deployment happen.

565
01:06:18,600 --> 01:06:23,600
You have to understand the connection between your code and what actually appears in Azure. Step three is putting that file in Git.

566
01:06:23,600 --> 01:06:30,600
Not for deployment purposes yet, just to experience version control as the source of truth. Write a clear commit message. Explain what you deployed and why.

567
01:06:30,600 --> 01:06:37,600
Create a branch. Make a small change to the bicep. Commit it. Look at the history. Revert the change. Pull it back.

568
01:06:37,600 --> 01:06:48,600
This is where the real power starts to sink in. Your infrastructure changes are now documented. They're traceable. They're reversible. You're not just learning bicep syntax. You're experiencing why version control is the foundation of everything we do.

569
01:06:48,600 --> 01:06:59,600
Step four is combining this with PowerShell. Don't replace your scripts yet. Just wire them together. The bicep defines the stage. The PowerShell performs on it. Deploy a function app and a storage account through bicep.

570
01:06:59,600 --> 01:07:05,600
Then write PowerShell that reads from that storage and logs to the function. You'll start to feel how the layers work together.

571
01:07:05,600 --> 01:07:30,600
Bicep handles the what? PowerShell handles the how? Step five is building your first module. Take your key vault bicep and make it reusable. Add parameters for the name, the location and the skew. Wrap it as a module. Deploy that module twice with different parameters. Create two different key vaults using the exact same code. This is where the exponential power of infrastructure as code clicks. You don't write infrastructure twice. You write it once and use it a thousand times. Different parameters. Same structure.

572
01:07:30,600 --> 01:07:50,600
This is how platform scale. None of these steps requires a massive time investment. You can do this in a couple of hours spread across a week. The point is you're learning through action, not passive study. You're building on each step. By the end of a week of genuine practice, you'll understand bicep at a level that no course can teach you. But here's the thing about the timeline. This isn't a sprint.

573
01:07:50,600 --> 01:08:17,600
Learning bicep and integrating it into your workflow takes months, not days. You're not trying to become an expert in a week. You're starting a transition that compounds over time. Every infrastructure problem you face becomes an opportunity to practice state thinking. Every script you write, you ask if bicep would be better. Every module you build makes the next one easier. This is a career shift. It's not just a skill update. That's why it takes time. It's not harder than powerShell. It's just different. It requires your brain to work in a different mode that rewiring takes practice and repetition.

574
01:08:17,600 --> 01:08:33,600
But once it happens, once you internalize the declarative approach, you can't unsee it. You won't want to go back to pure scripting because you'll finally understand why platforms matter. You'll see why governance scales through infrastructure. And you'll understand why the organizations paying the highest salaries are the ones thinking this way.

575
01:08:33,600 --> 01:08:42,600
The powerShell ceiling isn't a failure. It's a signal. It means you've outgrown task automation. You're ready for platform engineering. Bicep is the language of that next level.

576
01:08:42,600 --> 01:08:52,600
Combined with powerShell and graph, it's the architecture that scales. The market recognizes this. Organizations are paying for it. Your next move is simple. Stop writing scripts. Start defining infrastructure.

577
01:08:52,600 --> 01:09:02,600
If this changed how you think. Follow me, Mirico Peters, on LinkedIn, tell me what you're building with bicep. I read every message. And if you want more of this, subscribe to the M365FM podcast.

578
01:09:02,600 --> 01:09:14,600
We talk about platform strategy, architecture and the future of Microsoft 365. Leave a review. It helps more architects find this. Share this with your team. Especially if you're dealing with this right now.

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.