As it has been pointed out already here codeSubstitutes is a good option only when a fix is needed to be included into the runtime because there is no other way to make it through. This is the case when a stalled chain needs some change in the runtime, but as it is stalled, cannot produce any block, and thus, a runtime upgrade is not a possible way.
Usually the steps are:
Include the fix in the code(branch/release/version) from which the running, and stalled, runtime has been built out from.
Do not bump the spec version of the runtime. As the documentation reads, this is a code substitution and it will be used until a new runtime with a new spec version is applied.
Include this new wasm blob in the chain spec of your running chain under the map codeSubstitutes. Its key will be a block number, something recent or even the last block the chain has produced. And as value of this map, the wasm itself.
Then, the code substitution will be effective once the nodes are running again from the block number specified.
If a parachain, the next step will be getting this same wasm used in codeSubstitutes into the relay storage for your para. Usually a governance proposal would be needed in order to get this done. E.g. of a call that could be proposed: force_set_current_code(paraId, wasm_used_in_codeSubstitutes).