All systems

02 / Deployment / operations

Deployment should not
be a leap of faith.

A project-agnostic .NET 8 console tool that automates the Windows Service lifecycle — stop, backup, copy, verify, restart — and rolls back automatically if any step fails.

Source Open source
Ready Healthy Rollback State machine / reverse gear
State machine
Ready
WHATIF / BLAKE3

Select a failure point. The machine stops the happy path, restores the versioned backup, and returns the service to a previous valid state.

01 / Context

Manual deploys fail in undocumented ways

WinService.Deploy was built after too many manual Windows Service deployments left a service in a broken, undocumented state. A failed copy or a service that will not restart has no clean way back if the previous files are already gone.

Generic deployment tools either assume a Linux or container target, or they are too heavyweight to justify for a single Windows Service on a single box.

02 / Constraints

The dangerous moment is the middle of the cutover

The service has to stop before files change. The current release has to be preserved before anything is overwritten. The new build has to prove it arrived intact, then prove it can run.

If any of those steps fail, the previous release has to come back — including on a remote UNC target — without asking the operator to reconstruct it by hand.

03 / System

A state machine with a reverse gear

The tool walks a fixed lifecycle: validate configuration, stop the service with retry, write a versioned backup, copy the build, verify BLAKE3 hashes, start the service, then prune old backups by retention.

Failure at copy, verification, or restart restores the backup and attempts to return the service to a running previous state. Every step writes a timestamped line to a deployment log.

The same executable covers multiple services through appsettings.json rather than being hardcoded to one target.

04 / Decisions

Decisions made against constraints.

Decision / 01

Treat deployment as a reversible transition

Problem
A partial deployment can leave a service in an invalid, undocumented state. Alerting alone still requires reconstructing the previous release under pressure.
Decision
Create a versioned backup before files change, then restore it automatically if copy, verification, or restart fails.
Why
The tool exists because failed deploys were leaving production without a clean way back. Rollback is the product, not an afterthought.

Decision / 02

Verify the transfer, not just the copy

Problem
A copy that reports success can still be corrupt. Hashing hundreds of files also cannot be so slow that verification is skipped in practice.
Decision
Hash deployed files with BLAKE3 and compare them to the source before the service is allowed to start.
Why
BLAKE3 is fast enough at these file sizes that integrity checks stay in the default path. The threat model is corruption, not adversarial tampering.

Decision / 03

Rehearse the cutover with no side effects

Problem
A tool that stops production services needs a way to prove configuration — paths, service name, permissions — without taking the service down.
Decision
Ship a WhatIf mode that simulates the full lifecycle, including what rollback would do, with zero filesystem or service changes.
Why
A new target can be validated before the first real run. Dry-run is part of operational safety, not a developer convenience.

Decision / 04

Do not require a matching runtime on the box

Problem
Production Windows servers do not always have the matching .NET runtime, and requiring it adds a dependency the tool should not need.
Decision
Publish as a self-contained win-x64 executable that bundles the runtime.
Why
The deploy tool should run on a clean target with no prerequisites beyond Windows itself.

05 / Implementation

An orchestrated console, not a script pile

The program is a .NET 8 console app with dependency injection. WindowsServiceDeployment orchestrates the run. WindowsServiceController owns stop/start/retry. FileOperations copies and hashes. BackupManager writes and restores versioned backups.

Spectre.Console provides the interactive UI and progress. Configuration lives in appsettings.json: service name, source and destination paths, backup retention, retry counts, verification, and rollback flags.

Remote targets use UNC paths. Old backups prune on a retention window so disk use on the deploy target stays bounded.

06 / Behavior

How the system behaves.

  • Clean path Stop, backup, copy, verify, start, health. Success is reported only after the service is running.
  • Fail during copy The versioned backup is restored. The previous files return before the tool gives up.
  • Fail during verify or start Rollback is triggered, the previous release is restored, and the service is started from that known state.

07 / Result

What improved.

A failed deployment no longer has to leave the service down in an unknown file state.

Integrity verification stays in the default path because it is fast enough to keep.

WhatIf lets a new target be rehearsed before the first production stop.

08 / Reflection

What the work demonstrates.

Operational tools are judged on the failure path. The happy path is table stakes; recoverability is the design.

WinService.Deploy is small on purpose. The work was encoding stop, backup, verify, and restore as one reversible transition instead of a checklist in someone's head.

Next system

03 / Research / retrieval / AI

Reddit Research Tool

Open