I have a separate thread that writes changes back to disk at its leisure. There is also a special shutdown/restart mode that I can trigger which stops accepting input from the user and flushes everything to the db.
This can be implemented very simply and has lots of advantages all around.
You're fortunate your data fits in RAM. And it seems you don't have to worry about machine failure causing unwritten data to be lost despite having accepted it from the user?
Oh, you said earlier "I just switched my most intensive app to only use the database for backing up the data to disk and reloading from on startup" so I thought you meant you only read data from the database on start-up, hence all data fitting in core.
If you're reading data from it whenever you find the data isn't in core then aren't you using the database?
As for the "thread that writes changes back to disk at its leisure", how do you guard against machine failure after accepting data for writing but before it's been written?
This can be implemented very simply and has lots of advantages all around.