Choose a migration path

With the inventory in hand, every configuration and resource in your estate lands in one of four buckets. Think of them as increasing levels of effort and increasing levels of payoff.

Figure 1: The four migration paths. Effort and payoff both increase from A to D.

The four paths

Path A — Adapt in place.

Keep the module exactly as it is. Reference it through an adapter in a Microsoft DSC configuration document. Zero changes to resource code; the only thing that changes is the envelope around it.

Path B — Import compiled MOFs.

Use an import extension to translate MOF files into configuration documents, either on the fly at invocation time or as a one-time conversion you commit.

Path C — Rewrite script-based resources as class-based.

A moderate rewrite that unlocks the PowerShell 7+ adapter and sheds the Windows PowerShell dependency. The three functions become three methods.

Path D — Rewrite as a native command resource.

Full modernization: a resource with its own manifest, invoked directly by the engine with no PowerShell host in the middle. Worth it for resources that need speed, cross-platform reach, or freedom from PowerShell hosting entirely.

[!NOTE]
"Native" describes how the engine invokes the resource, not the language you write it in. Technically, a command resource can still be PowerShell: the resource manifest calls pwsh and hands it a PowerShell script as the entry point. PSResourceGet ships its DSC resources this way.

"get": {
  "executable": "pwsh",
  "args": ["-NoLogo", "-NonInteractive", "-NoProfile", "-Command", "./appenvironment.ps1 get"],
  "input": "stdin"
}

You gain the manifest's full capability surface without leaving PowerShell. You don't gain the near-instant startup, because every invocation still starts pwsh.

Compare them honestly

Path A Path B Path C Path D
Effort Hours Hours Days Weeks
Resource code changes None None Rewrite Rewrite in another language
Requires 5.1 at runtime Yes Yes No No
Works cross-platform No No Yes (PowerShell 7) Yes (native binary)
Startup cost per invocation PowerShell host PowerShell host PowerShell host Near-instant
Full capability surface No No Partial Yes
Best for Everything, as a first move MOFs with no surviving source Resources you'll keep for years Resources invoked constantly, or shipped as products

[!NOTE]
The effort estimates assume a person doing the work by hand, without AI assistance. AI tools can shorten the typing, but they don't shorten the review, the testing, or the edge cases you still have to verify on a real machine. Apart from the aside in Figure 1, this course leaves AI out of every estimate.

A decision flow you can defend

Work down this list per resource. The first match wins:

Figure 2: The decision flow per resource. The first match wins.

[!IMPORTANT]
Paths A and B are not failures of ambition. They move the orchestration layer to Microsoft DSC while leaving resource code alone, which is exactly the decoupling that makes Paths C and D safe to do later, one resource at a time, with a working system between every step.

When Path D earns its cost

Rewriting working PowerShell into another language is a real cost that needs a real payoff. Four signals tell you a resource has outgrown the adapter:

  • Startup cost dominates. Every adapted invocation pays for a PowerShell host. For a resource invoked constantly — by a scheduler, a pipeline, or an AI agent — a native binary's near-instant startup changes the economics entirely.
  • You need platforms that PowerShell modules serve poorly. A native resource compiled for Linux and macOS beats "install PowerShell 7 everywhere first" as a deployment story.
  • You want the full capability surface. Native what-if support via whatIfArg, implementsPretest, handlesExist, and fine-grained capability declarations belong to resource manifests, not to adapted resources.
  • The resource is a product, not a script. If other teams or customers consume it, the single-binary distribution model and the language-agnostic contract are worth the rewrite on their own.

If none of those apply, a class-based resource running on PowerShell 7 through the adapter is a fully supported, long-term-viable end state.

Apply it to Bindery

Run the decision flow against the estate you built in unit 4:

Artifact Decision flow result Path
LegacyWebServer.ps1 Source script exists, resources are script-based A
output\localhost.mof Source exists, so the MOF is redundant — but you'll convert it anyway to learn the tool B (as a drill)
BinderyOps/AppEnvironment Script-based, still owned, no Path D signals A now, C next
PSDesiredStateConfiguration/File Built-in, script/binary-based, owned by Microsoft A (or replace with a native file resource later)

That last row is worth pausing on. Some of your estate isn't yours to rewrite. Built-in PSDesiredStateConfiguration resources migrate via Path A by definition — the question is whether a native Microsoft DSC equivalent exists that you'd rather use instead. Check before you adapt.

[!TIP]
Record the chosen path in the inventory itself, next to the owner. When someone asks in six months why AppEnvironment is still on the 5.1 adapter, the answer should be a row in a file, not a memory.

> EOF