We use this pattern in our Ruby apps to safely move $1B+/month at Gusto.
You don’t need full blown monads to do this, just need to be cognizant to how you separate the what (functional core) from the how (imperative shell). I recommend giving it a try!