This was a very high-effort post so I thank you for sharing it. It is very useful feedback for everyone to read.
However, in the specifics, I have to question essentially every technical choice you've made given that you've framed things as "toys" vs "production". First, on the topic of receiving large file uploads, having your web server handling this is just not a good choice for an actual production web service. It is trivial to create a pre-signed upload url for all of the major object stores (S3, GCS, B2, R2, etc). This means your clients can upload an arbitrarily large file, after authenticating, with essentially infinite scalability and without placing any load whatsoever on your web server. There is no way to beat this when the cost of these services is so low. Let me share a concrete example. As part of a production service I run, we receive small but frequent file uploads. In the past 3 months, 6.7 million files have been uploaded taking up 2.6 TB of storage. Guess how much this costs me all-in? Less than $20/mo on Backblaze B2. Just the harddrive space for a VM in any cloud anywhere would cost massively more than this, let alone managing the compute etc. It's just a horrible horrible horrible horrible idea not to use an object store basically always. These also solve your download / streaming problem just like that. You may say you want to self host everything. Fine, but just know you've left the realm of production web service and are prioritizing things other than engineering excellence without a very very good reason. You really focus on request streaming being a deal breaker but to me that is a self inflicted problem. You'll never overcome the cost effectiveness of something like B2 or R2 or whatever, and streaming is only relevant for these very large files (like video). Speaking of large files and video, you also seem to be ignoring the fact HTTP supports Range requests. This is fundamental to skipping around in a video without downloading the whole thing. Something that seems pretty darn fundamental in a production service. Range requests also completely remove the need for streaming. Ok so now that file uploads, downloads, streaming and video have been counter-pointed, lets take on the reverse proxy issue. Choosing to use a reverse proxy is not at all an admision something isn't ready for production. In fact, not using a reverse proxy reveals you're not actually thinking about a real production web service at all. Why? Frequently deploying new code without any downtime or users even noticing is absolutely fundamental to a real web service. Let me explain exactly the issue. If you do not have a reverse proxy, then you have exactly one web server serving on your production IP. The only way to then deploy new code is to kill the currently running process and start a new one (unless you try to do IP based rollouts through DNS but that is just horribly slow and terrible). Ok so every time you deploy code you'll be breaking things for clients, cool, not exactly great in production. Imagine your large file uploads or streaming downloads and how they feel about you deploying code. It's a horrible situation to put yourself in, makes shipping code way too painful, and completely avoidable. With a reverse proxy / load balancer, I, personally, can bring up 1 or more new production servers at any time. I can then run some validation scripts against those servers in their production environment to ensure they are good to go, then I can gradually shift traffic to those new servers and revert this process at any time if I notice issues. Do you see how much better this is for an actual production service? I deploy 10+ times in a day if I am working on things because it is painless and helps me ensure I'm not breaking things every step of the way. You are correct that Nim has opportunities for improvement on the HTTP side of things, and believe me I agree, however I don't think it is quite for the reasons you've laid out. Nor is it so dire. I hope this post has opened your eyes to a larger picture of what a production service is and why some of these tools like object stores and load balancers are so helpful once you're out of the toy phase.