
Moving data-intensive systems to different software without losing data or running into days of downtime is part of my core business. The way I go about it is best shown with a real example from my own infrastructure: a service holding around one terabyte of data.
The example happens to be a Bitcoin node, but the specific context is secondary. The underlying principle applies just as well to a mail server, a database, or a NAS. It is the method that matters, not the application.
The trigger
I had been running the node on Bitcoin Knots and switched to Bitcoin Core. The reason was a sober risk decision: newer Knots versions enforce a new rule set (BIP-110) that, in early August 2026, led to a split into a barely functioning minority chain. My node should stay where the ecosystem actually operates – not enforce a rule experiment with an open outcome. The leaner data handling I valued in Knots can also be configured in Core with just a few lines. That settled it: switch to Core – but without re-downloading the terabyte.
And that’s exactly where the real work begins.
1. First analyse where the data lives
The most common mistake in migrations is to swap the software and hope. On the platform in use (Umbrel), the old and the new software are two separate applications, each with its own data folder. A simple “remove the old, install the new” would have triggered a complete re-download. Understanding beforehand where the data physically sits is exactly what saves you that.
2. Always work with a way back
Before touching anything, everything that holds state is backed up (configurations, payment channels). Then all dependent services are stopped cleanly – in my case several applications were hanging off the node – so the database is in a consistent state. Only then is anything moved. And the old software stays installed until the new setup is proven to run: the migration must be reversible at any time.
3. Move instead of re-download
Instead of a re-download, the existing data folder is moved from the old application to the new one.
⚠️ Warning – do not copy this blindly. The following command contains an irreversible deletion (
rm -rf) of the target data folder. A wrong folder name destroys data. Run this only with all services fully stopped, and check the actual folder names on your system beforehand withls umbrel/app-data/.
cd umbrel/app-data/ && sudo rm -rf bitcoin/data/ && sudo mv bitcoin-knots/data/ bitcoin/ && sudo rm -f bitcoin/data/app/bitcoin-config.json
The command removes the empty new data folder, moves the existing data across, and deletes the carried-over old configuration so the new software generates its own. The service then starts – and does not begin from zero, but is immediately at the current state. What could have been a multi-day project becomes a few minutes of downtime.
4. Verify, don’t trust
For me a migration isn’t “done” when the service starts, but when I have proven that it works:
- Is the new software actually running? Query the version directly at the service, not just in the dashboard.
- Is the intended configuration taking effect? Cross-checked via the service’s status instead of assuming it.
- Is the service reachable from outside? Tested externally. A classic trap lurks here: an “enabled” toggle in the interface does not yet open a port in the server firewall. Only the external test confirms what’s configured internally.
- Read the logs correctly. Most of what looks like an “error” is harmless operational noise. Knowing which message can be ignored and which cannot is the difference between panic and diagnosis.
For technicians: my filter rules in Bitcoin Core
The leaner mempool policy I used to value in Knots I set in Bitcoin Core with just a few lines of configuration:
datacarrier=1
datacarriersize=83
permitbaremultisig=0
datacarriersize=83 limits embedded data (OP_RETURN) back to the classic ~80-byte limit – since version 30, Core otherwise allows up to 100,000 bytes. permitbaremultisig=0 additionally rejects bare multisig, an old vector for embedding data. Important: this is purely local relay policy, not an intervention in the consensus rules. The node stays fully compatible with every other node and only decides for itself what it accepts into its mempool and relays onward. Core’s filters are deliberately narrower than those of Knots – for my purpose they are enough, without accepting the split risk of the Knots rule.
What this means for your systems
A software switch on data-intensive services doesn’t have to mean a rebuild, as long as you know where the data lives. Backup and a way back belong to every migration, and a service only counts as migrated once it has been verified – reachability, configuration and version are proven, not assumed.
Whether it’s a node, a mail server, a database or an entire server: if a system of yours needs to move and you don’t want to take any risks doing it, I’ll handle it for you – methodically, documented and without data loss.

