

In addition to backups, consider using snapshots if your file system supports it (ZFS, Btrfs, or LVM).
I use ZFS and have each of my Docker volumes in a separate ZFS dataset (similar to a Btrfs subvolume). This lets me snapshot each container independently. I take a snapshot before an upgrade. If the upgrade goes badly, I can instantly revert back to the point before I performed the upgrade.
This is how I handle it for most software: Read (or at least skim) the changelogs for all minor and major versions between your current version and the latest version.
If you’re using Docker, diff your current docker-compose to the latest one for the project. See if any third-party dependencies (like PostgreSQL, Redis, etc) have breaking changes.
If there’s any versions with major breaking changes, upgrade to each one separately (eg. 1.0 to 2.0, then 2.0 to 3.0, etc) rather than jumping immediately to the latest one, as a lot of developers don’t sufficiently test upgrading across multiple versions.
Take a snapshot before each upgrade (or if your file system doesn’t support snapshots, manually take a backup before each upgrade).
…or just don’t read anything, YOLO it, and restore a snapshot if that fails. A lot of software is simple enough that all you need to do is change the version number in docker-compose (if you’re using Docker).