96 Azure Local redeployments in two weeks — because the order never slipped.
A redeployment is a long chain of destructive steps that have to happen in the right order, from Azure prerequisites and BitLocker to OS install, storage reattach, VM import, and HA roles. This is the PowerShell console that kept that order — first version in about a day, hardened over the program. It previewed the risky steps, tracked every site, and logged commands by site. That discipline, not any one clever script, is how one engineer cleared 96 sites.
The risk wasn't any single step. It was losing the order.
Redeploying an Azure Local site is not one action — it's a long, branching runbook: Azure prerequisites, pre-migration checks, BitLocker, cluster shutdown, OS install, post-deploy validation, storage reattachment, VM import, HA role creation, VM version upgrades, and a final workload health check. The steps are destructive and order-dependent. BitLocker comes off before the rebuild and goes back on only once storage and VMs are back; HA roles can't exist until the VMs they protect are imported. Swap two steps and you find out on production hardware.
Doing that once carefully is fine. Doing it 96 times in two weeks, alone, with a dozen sites in flight, is where humans drop steps. The real failure mode wasn't "I don't know the command" — it was "which site am I on, what did I already run here, and is it safe to run the next thing yet?" The console exists to answer exactly those three questions, every time.
A guided runbook, not a folder of scripts.
Right order, every site, and a log to prove it.
Three problems between one site and ninety-six.
None of them was a missing cmdlet.
A dozen sites in flight, one operator. Batches ran twelve sites at once — ninety-six is eight waves of twelve. A 12-site dashboard showed each one by stage, with current and planned work, attention items, and the latest evidence. That removed the decision tax. A site that failed mid-run was resumable, not a forensic exercise, and a slow one could wait without me re-deriving its state from memory or scrollback. The throughput came from the ordering and the log, not the scripts they wrap.
Every node had to start identical. Hand-built installs drift, and drift at site sixty is a mystery. An unattended ISO stages the deployment payload, site data, post-deploy scripts, and NIC drivers. After install, a day-0 helper sets up local admin access, installs the drivers, prepares the Configurator values, validates the management IP source preference, and writes logs for later review. Every node started from the same place, with receipts.
A DNS check that lived in 1601. In August, the console's recurring post-deploy checks moved into The Forge as governed commands, and the port caught one that had been confidently wrong. Static DNS records carry an aging timestamp of 0, which CIM renders as the year 1601, shifted into local time. The console only treated null, "0", or MinValue as static, so it reported every static record as dynamic. The Forge version treats anything before 1602 as static, keeps the raw values, and returns Warning when it can't verify. The migration sequence itself stayed in the console, on purpose: it's operator-paced work, not a job for a queue.
It started scrappy: a working first version in about a day, pointed at one job — keep a solo operator on-rails across many high-risk migrations. By the end it was 15 core scripts and about 8,400 lines of PowerShell. No client data here, and the console graphic above is illustrative. Want the ordering-and-audit pattern walked through for your own migration work? Ask me about it →