Automatic Updates
Stale installs are the default failure mode of desktop software. Automatic updates (or reliable package-manager updates) are essential for security fixes, compatibility, and supportability—above all on Windows, where users often never revisit your download page.
Framework: Software Product Essentials. How-tos:: Windows · macOS / Linux Desktop template:: Desktop auxiliary features
Goals
-
Users reach a patched build without hunting zip files
-
Updates are channel-aware (stable vs beta)
-
Failed updates do not brick the install (rollback or last-known-good)
-
Enterprise environments can disable or pin when needed
-
Apply steps respect locked files and running processes on every OS
Strategy ladder (prefer left when enough)
-
Platform package manager / store — winget, MS Store, Mac App Store, Homebrew, apt/dnf, Flatpak, Chocolatey, Scoop
-
Installer that upgrades in place — MSI major/minor upgrade, MSIX, Sparkle-fed DMG, etc.
-
In-app updater — checks a feed, downloads, verifies signature, stages bits, quits, swaps, relaunches
-
Manual download page — last resort; document it; never the only path for a 1.0 GUI app
Many products combine (1) + (3): package manager for discovery/install, in-app for faster channels.
Apply safety (all desktop OS)
Updating is not “download over the EXE.” Common failure modes:
-
Windows file locks while the app (or tray helper) is running
-
Linux
ETXTBSYwhen writing over a running ELF; inode confusion if you replace the path while the old binary keeps running -
macOS mapped frameworks inside a live
.appbundle
Canonical sequence: prompt → save state → quit process tree → wait for PID exit → verify artifact → replace → relaunch → show What’s new. Package managers often own stop/start for you—prefer that on Linux. Details and stubs: Unix/macOS auto-updates, Windows auto-updates.
Scheduled upgrades (kiosk/daemon hosts) belong in systemd timers / unattended-upgrades / Flatpak timers with a narrow package allow-list—not a blind full-system upgrade spawned from the GUI.
Windows-specific reality
Windows users expect one of:
-
Microsoft Store / MSIX — store handles updates
-
winget-upgradable installer — ARP entry + winget manifest with installer URL and version
-
In-app updater — common for apps outside the Store (electron-updater, Velopack, custom WinSparkle-class, Squirrel legacy, etc.)
Avoid “download Setup.exe from the website every time” as the primary story. Prefer:
-
Code-signed installers
-
Silent/upgrade-friendly packaging
-
A clear Apps & features uninstall entry
-
Update checks that respect metered networks and “do not disturb” work hours when reasonable
-
Swap-on-restart when files stay locked
See also: Winget registration, Distribution and packaging.
macOS and Linux reality
| Channel | Notes |
|---|---|
Mac App Store |
OS-managed updates; still show in-app version/build for support |
Sparkle-class (macOS direct) |
Notarize; signed appcast; quit → replace |
Homebrew cask |
Power-user path; About should mention |
apt/dnf/zypper / Flathub / Snap |
Preferred Linux story; app may stub “update via your package manager” or run a privileged oneshot after quit |
AppImage / portable |
Stage beside → wait for exit → atomic rename → exec; never write into the running file |
Update feed design
Minimum feed fields:
-
Version (comparable)
-
Channel
-
Artifact URL(s) per OS/arch
-
Signature / hash
-
Minimum OS version
-
Release notes URL or inline summary
-
Mandatory flag (for broken releases)
Pin the feed URL in the binary; allow enterprise override via policy/config.
Safety
-
Verify signatures / hashes before apply
-
Stage then swap; keep previous build for rollback when feasible
-
Do not run the updater as a confused admin forever—prefer per-user installs when elevation is not required
-
Never phone home with PII just to check versions; a build id + OS/arch is enough
When auto-update is wrong
-
Locked-down fleets that require IT-approved MSI via GPO/Intune — offer a disabled updater and an IT package
-
Libraries — consumers update via their package manager (npm, crates.io, DUB, …)
-
One-shot scripts — document version; do not self-mutate the user’s PATH tools unexpectedly