
In this blog, we’ll break down Desired State Configuration (DSC). What it is, why it still matters, and why Microsoft didn’t just update it, but rebuilt it entirely in DSCv3.
Introduction to Desired State Configuration
Microsoft’s PowerShell Desired State Configuration (DSC) has been part of the Windows configuration management ecosystem since PowerShell 4.0. Introduced in 2013, it allowed administrators to define infrastructure as code and enforce configuration over time. Instead of scripting every action, you described what the system should look like, the “desired state,” and DSC handled the rest.

That PowerShell Desired State Configuration model worked well for its time, but infrastructure practices didn’t stand still. As demand for cross-platform support increased and infrastructure as code matured, teams began favoring Git-backed CI/CD pipelines over traditional agent-based management models. Managing configuration through background agents like LCM or legacy tech like WMI/WinRM no longer fits the model. Microsoft responded by redesigning PowerShell Desired State Configuration from the ground up, driven by the limitations of the original Windows-only architecture and the need to support modern, cross-platform development workflows.
And yet… MOF isn’t gone. While one team removed it entirely, another brought it back. Intune’s MMP-C stack utilizes MOF fragments internally through WinDC, its cloud-based policy engine. Therefore, you may now write YAML for DSC v3, but still end up dealing with MOF-based enforcement on managed endpoints.
This article guides you through the changes, explains why they matter, and helps you determine when and if to migrate to Desired State Configuration v3.
What Desired State Configuration v2 Looked Like
Before diving into DSC v3, it’s worth understanding how PowerShell DSC v2 worked and why it eventually became a limiting model.
PowerShell Desired State Configuration (DSC) v2 was built around the Local Configuration Manager (LCM). This engine ran on each node and was responsible for applying and enforcing its configuration. It worked by checking the system at regular intervals, reading its current state using Get-TargetResource, comparing it to the desired state using Test-TargetResource, and correcting it if needed using Set-TargetResource.
This get-test-set workflow defined how DSC enforced configuration, but it also introduced complexity. Writing resources meant dealing with schema.mof files, strict function definitions, and deep PowerShell knowledge. Cross-platform support was non-existent, and even supporting new Windows scenarios often required significant effort.
To define configuration, we needed to write .ps1 scripts using a special declarative syntax. These were compiled into MOF files and either pushed to the node or pulled from a central server. Everything relied on PowerShell 5, WMI, and WinRM, all delivered through the Windows Management Framework (WMF).
But as infrastructure and development practices evolved, this model became harder to maintain. The LCM engine was deeply tied to Windows-only technologies and could not be easily extended or integrated into modern toolchains. Rather than trying to retrofit those limitations, Microsoft chose to redesign DSC entirely, resulting in DSC v3.
Why Microsoft Rebuilt Desired State Configuration v3
Rather than evolving the existing Desired State Configuration engine, Microsoft decided to start fresh. The original implementation was tied closely to Windows internals like WMI, WinRM, and the .NET Framework. These dependencies made it increasingly challenging to modernize or extend beyond the Windows ecosystem.
Desired State Configuration v3 takes a different approach. It introduces a lightweight CLI tool called dsc.exe, written in Rust, that runs across Windows, Linux, and macOS. It doesn’t rely on MOF files, background services, or Windows Management Framework components. Instead, it applies declarative configuration files, which are written in YAML or JSON, when explicitly invoked.
This design trades in automatic enforcement for portability and simplicity. Features previously handled by the Local Configuration Manager (LCM), like drift correction, versioned pull servers, consistency checks, and reporting, are no longer part of the product. If you need those capabilities, you’re expected to build them yourself using CI/CD, cron jobs, or scheduled tasks.
Desired State Configuration v3 isn’t trying to replace everything Desired State Configuration v2 did. It focuses on applying configuration, not managing it continuously. That shift means less overhead, fewer assumptions, and a better fit for environments that already rely on pipelines to control deployment timing.
How to Install Desired State Configuration v3
DSC v3 is distributed as a standalone CLI tool called dsc.exe. There’s no agent or service. Just download and run it. On Windows, you can install it using Winget:
winget install Microsoft.DSC
⚠️ Note: DSC v3 requires PowerShell 7.2 or later to run PowerShell-based adapters. Since Windows Server 2025 still ships with Windows PowerShell 5.1, you’ll need to install PowerShell 7.x separately. You can do that manually, or from an elevated PowerShell prompt using:
winget install –id Microsoft.PowerShell –source winget
On Linux or macOS, download the latest release from GitHub:
👉 https://github.com/PowerShell/DSC/releases
Extract the binary, place it in your PATH, and you’re ready to go.
DSC v3: Example YAML Configuration
Below is a basic example of a DSC v3 configuration that ensures a specific registry key is present. This could be used to enforce a group policy setting or reapply a compliance rule at runtime.
# yaml-language-server: $schema=https://aka.ms/dsc/schemas/v3/bundled/config/document.vscode.json
$schema: https://aka.ms/dsc/schemas/v3/bundled/config/document.json
resources:
- name: Ensure PatchMyPC Key
type: Microsoft.Windows/Registry
properties:
_exist: true
keyPath: HKLM\SOFTWARE\Patch My PC
- name: Ensure DesiredStateTest Value
type: Microsoft.Windows/Registry
properties:
_exist: true
keyPath: HKLM\SOFTWARE\Patch My PC
valueName: DesiredStateTest
valueData:
DWord: 1
This configuration ensures that the DesiredStateTest registry value exists under the specified key with the correct data and type. If someone changes or deletes the value, DSC can detect the drift when tested
Once tested, you can (re)apply the desired state manually using dsc config set.
Note: DSC v3 does not utilize a background service or Local Configuration Manager (LCM), unlike previous versions of DSC. It won’t monitor or reapply the configuration automatically. You must trigger it explicitly using a script, scheduled task, or CI/CD pipeline.
Orchestration and Drift Detection with DSC
In DSC v2, the Local Configuration Manager enforced configuration automatically in the background. It handled periodic checks, re-applied settings when drift was detected, and operated under the SYSTEM context by default.
DSC v3 does not include any of this functionality. There is no built-in timer, no polling mechanism, and no background service. Configuration is only applied when explicitly executed. This gives administrators full control over when and how DSC runs, but it also means you are responsible for ensuring enforcement happens when needed.
To apply or test a configuration with DSC v3, you invoke the CLI directly:
dsc config test --file config.yaml
dsc config set --file config.yaml
If you need continuous enforcement or scheduled reapplication, you must implement that using one of the following methods:
- CI/CD pipelines – Integrate DSC execution into GitHub Actions, Azure DevOps, or GitLab pipelines
- Scheduled tasks – Use Windows Task Scheduler or cron on Linux or macOS
- Custom agents or services – Build lightweight daemons that mimic LCM-like behavior
It’s also important to remember that dsc.exe runs in the user context. If your configuration requires elevated access (such as writing to HKLM or Program Files), it must be executed with administrative privileges.
If you previously relied on LCM for enforcement, drift correction, and SYSTEM-level execution, you will now need to rebuild those pieces manually. DSC v3 assumes that orchestration is handled externally, and that approach aligns with modern infrastructure practices based on pipelines and automation.
How the Adapter Model Works
DSC v3 removes the use of PowerShell classes and MOF schemas and introduces an adapter model. Each resource consists of a .dsc.resource.json manifest and one or more scripts or binaries that implement three required operations: Get, Test, and Set. These are called by the DSC engine, which passes input and output as structured JSON over standard input and output.
Here’s a simple example of a PowerShell-based adapter manifest:
{ "name": "MyCompany/File", "entryPoint": "./file.resource.ps1", "type": "script", "operations": ["Get", "Test", "Set"] }
When dsc.exe runs, it reads this manifest, calls the adapter’s entry point, and passes input and output as JSON.
Adapters can be:
- PowerShell scripts (using pwsh)
- Bash scripts
- Compiled CLI tools (like Go or Rust binaries)
The adapter model is flexible, but not necessarily simple. You are responsible for maintaining strict structure and idempotent behavior. Each adapter must correctly separate the logic for reading, testing, and applying configuration, and must adhere to the JSON schema expected by the DSC engine.
Existing DSC v2 resources can still be reused if wrapped inside a proper adapter. There is no automatic compatibility. You must build the bridge script to expose the required operations in the correct format.
To confirm your adapters are registered and available to the DSC engine, use:
dsc resource list
And Yet Microsoft Is Using MOF Again
Although DSC v3 no longer uses MOF files, Microsoft’s other systems, like Intune’s (using WinDC), still depend on MOF fragments for policy enforcement. The MMP-C stack processes partial MOF content behind the scenes as part of its device configuration engine.
This means that while you may define configuration using YAML in DSC v3 for your servers, MOF-based logic may still apply on managed endpoints via Intune.
Let’s take a closer look at the feature comparison table before considering when and how to migrate from PowerShell DSC v2 to DSC v3
Feature Comparison Table
Feature | DSC v2 | DSC v3 (Rust CLI) |
---|---|---|
Runtime Engine | PowerShell with LCM | Rust CLI (dsc.exe) |
State Methods | Get / Test / Set | Adapter-driven Get/Test/Set |
Config Format | .ps1 to MOF | YAML or JSON |
Shell or Language Support | PowerShell 5 only | PowerShell, Bash, Python, Go |
Enforcement Model | LCM background agent | Orchestration by CI/CD or cron |
Context | SYSTEM | Userland (unless elevated) |
Pull Server Support | Yes (with versioning) | No |
Export or Reverse Config | Scripting only | Built-in (planned) |
Assertions / Conditional Logic | Script-based | Native assertion resource |
Data Flow Functions | Manual parsing | Built-in cross-resource logic |
GitOps Integration | Manual | Compatible with CI/CD |
Migration Guide for Desired State Configuration v3
DSC v3 isn’t a drop-in upgrade, it’s a complete re-architecture. Migration is possible, but it comes with tradeoffs. You should consider moving to DSC v3 if:
- You need to manage both Windows and Linux systems using a single tool
- You want to adopt GitOps-style workflows and integrate configuration into your CI/CD pipelines
- You prefer YAML or JSON over MOF and want to avoid the Windows Management Framework
- You’re eliminating legacy dependencies like WinRM or LCM
What to Expect
- DSC v3 removes built-in enforcement, drift correction, pull servers, and version tracking.
- There is no SYSTEM-level agent. Configuration is only applied when you explicitly run it.
- Orchestration, scheduling, and reporting are now your responsibility.
Migration Steps
- Rebuild Resources
Replace class-based PowerShell Desired State Configuration v2 resources with adapter-based implementations using the Get, Test, and Set model. You’ll still need to structure logic carefully and ensure idempotency, which hasn’t changed. - Convert Configuration
Convert .ps1 and MOF-based configurations into YAML or JSON.. There’s no compiler, you author and run configuration files directly. - Implement Orchestration
Replace the pull server model with pipelines, scheduled tasks, or service wrappers. DSC v3 provides no scheduling or versioning. - Wrap Existing Logic
PowerShell DSC-based logic from v2 can be reused, but only if wrapped in a proper adapter. There’s no automatic compatibility.
Proceed Gradually
You can run DSC v2 and v3 side-by-side. For example:
- Continue using LCM for existing nodes
- Use DSC v3 for new workloads that fit into GitOps or CI/CD pipelines
- Migrate resources and nodes incrementally
Not for Everyone
DSC v3 is better suited for environments where you control your orchestration and are prepared to handle scheduling, drift detection, and reporting externally. If your workflow depends on built-in compliance tracking, automatic correction, or deeply integrated PowerShell modules, tools like Ansible or Chef may offer more out-of-the-box functionality.
Final Thoughts
DSC v3 drops the agent model and leaves configuration enforcement up to you. There’s no automatic drift correction; you decide when and how the desired state gets applied.
But drift still matters. Even with DSC handling the system layer, keeping applications up to date is just as critical. That’s where Patch My PC helps, ensuring software stays in a known, supported state across your devices.