I’m thinking about rewriting my web server apps in Rust.
Right now, this website is being served from a Go app I wrote. It’s a web server app, but also handles DwayneBot and my RSS reader. It’s all one executable running on one physical web server.
There’s a lot of things I like about Go (simplicity and speed mostly), and a few I don’t. As I was thinking about future plans for the website, I started thinking about rearchitecting things and potentially switching languages.
All of the hardware I’m using is rented from Digital Ocean. I’m using a managed Postgres server and one Droplet (Ubuntu server) for all the dwayne.xyz services. Eventually I want at least one additional CPU focused Droplet for self-hosted live streaming, and potentially one more cheap/small server to put some of the secondary services (TURN/STUN server, LibreTranslate, IRC, etc) on.
The services I run (and wrote myself) on this Droplet are:
- Web Server - Calls third party APIs, connects to my database, exposes an API, and serves HTML
- RSS Reader - Requests and processes RSS items from my list of feeds (you can see the result here)
- DwayneBot - Accepts and processes questions and commands, provides a REST API and WebSocket endpoints (you can see how it responds here)
- chat-bot - A badly named server process that connects to both the DwayneBot process and IRC/Twitch chatrooms
Secondary services (I didn’t write these):
- TURN/STUN Server - For the WebRTC based chats I host here
- IRC Server
- Gitea - My code repos
- Fathom - For website analytics
All of the services in the first group (besides chat-bot) are part of the same Go server process. It and the chat-bot process communicate through WebSockets.
In order to actually take advantage of multiple Droplets, I’m thinking I should split all the stuff I wrote into the following:
- API/Backend service
- RSS reader service
- Web server
- DwayneBot service
- chat-bot service (I really need a better name for this)
And use something more efficient than WebSockets to communicate directly between them (like any built-in IPC/RPC mechanism). And then something like memcached as a shared cache for all of them.
So why do all this?
- Update, restart, and move (between Droplets) processes more easily
- I can add more Droplets and/or services to the system in a more organized way
- It’s a good opportunity to rewrite and improve parts of this project
- I can pick a more exciting/interesting language than Go
- Lose some simplicity and efficiency
- Rewriting all this code will take some time
- Every time I start mentally planning this out and reviewing what I have so far, I realize how much I really like what I have so far
- The setup I’m using can already support many, many times more visitors than I’m currently getting, so this is definitely unnecessary from a performance/price (Droplets aren’t cheap) perspective
I mentioned using Go a few times. It’s actually served me really well this whole time and I’m not sure I really want to stop using it. But, part of my motivation for all of this is to learn stuff and keep myself up to date so I started thinking about what I might use instead. Some of the options:
The new thing. Fast, modern, memory safe/efficient. The only problem is I just don’t like the syntax. Like… it’s fine, but I’m just not that excited about actually reading/writing the code.
Yes, C++. I’ve been using it for some Linux GTK development lately and I miss it. I’ve heard good things about some of the C++ web server frameworks that are “popular” these days. But I wouldn’t really be keeping myself up to date by using a language that’s literally as old as I am.
I could just stick with Go and either change the architecture anyway or just… leave things the way they are. One thing that’s been on my mind about Go is the recent addition of Generics. Generics are great, but so far this implementation feels kinda bolted on just because there were too many complaints about them being missing. I’m not looking forward to an awkward couple of years of all the libraries trying to figure out the best way to implement them.
I’m not really considering Java (even though Clojure is one of my favorite languages), PHP, Ruby, Python, or .NET.
I still haven’t decided what to do. If I choose another language, I estimate it’ll take a few months before I can start testing. So it’s probably worth just trying a few things out over the next few weeks and see what feels right.
Time to start writing some more Rust.