The apps were made long before Docker was a thing, so they just run as regular ol' processes, locked down as much as possible with systemd magic. I originally used uwsgi as my wsgi server, but it turns out gunicorn is vastly more efficient so I use it exclusively now.
I run a warm standby server at Hetzner so I can route traffic there in a pinch. I have a second warm standby running at my house because I'm truly paranoid about automated account bans (despite the very innocuous nature of my business). Backups are at rsync.net.
My single point of failure is DNS. I had a good relationship with DNSMadeEasy so I was not too worried about automated bans. But they were just bought by DigiCert, so that's a problem now.
Payments are handled with Stripe and PayPal. I added PayPal (despite my hatred of the company) just because I'm scared Stripe will ban me without warning, for no reason, and won't communicate with me.
For user uploads, I have an aiohttp Python server that streams files to Wasabi and Backblaze, and caches them in nginx at the same time. So my cloud bandwidth bill is usually 0.
The websocket layer is kind of wonky. Originally, I used the Python websockets asyncio library to do everything. It worked for a while, and then I had to make it multi-process to spread the load. But it was just eating resources like crazy. I decided to use OpenResty's websocket stuff to handle the connections, but I didn't want to write all the complex application logic in Lua. So I used Redis pub/sub to pass messages back and forth from OpenResty-land to a pool of (sync) Python processes. It worked much better. That said, I'm a novice with asyncio, so I could very easily be to blame for the original performance problems.
And sorry, I won't tell you the name of my apps (I don't need any more competitors!)