Cloudflare Workers support WASM, which is how they support any runtime beyond JavaScript. Cloudflare Worker's support for WASM is subpar, which is reflected even in things like the Terraform provider. Support for service bindings such as KV does not depend on WASM or anything like that: you specify your Wrangler config and you're done. I wonder what you are doing to end up making a series of suboptimal decisions.
The worker model made sense, so I developed the whole app around it. Now of course, knowing what I know today, I might have considered different options. But at the time, I read the description (and had some Cloudflare Workers experience) and thought this looked good.
Then you'll still not beat a good self-managed VPS but you'll have someone else to blame
1) Creating and restoring backups
2) Unoptimized disk access for db usage (can't be done from docker?)
3) Disk failure due to non-standard use-case
4) Sharding is quite difficult to set up
5) Monitoring is quite different from normal server monitoring
But surely, for a small app that can run one big server for the DB is probably still much cheaper. I just wonder how hard it really is and how often you actually run into problems.
But to answer your question: running your own DB is hard if you don't want to lose or corrupt your data. AWS is reliable and relatively cheap, at least during the bootstrapping and scaling stages.