As we continue building out hosted.md, one of the key decisions has been choosing where and how your websites will actually be hosted. It might sound like a small behind-the-scenes thing, but it's the foundation for how fast, reliable, and flexible the service can be. This is especially important when you're uploading HTML files and expecting them to show up quickly under your own domain.
At first, we looked closely at AWS and its popular S3 storage system. It’s powerful, well-documented, and something many developers are familiar with. But after testing and comparing it with Cloudflare’s R2 storage and CDN setup, the decision became pretty clear. Here's why.
✅ What hosted.md Needs from a Hosting Provider
Before diving into the options, here's what we knew we needed:
- The ability to upload static HTML files and serve them from a hosted.md subdomain
- Support for custom domains so your site can live at yourname.com
- SSL so all sites are secure by default
- Low operational overhead, especially when managing infrastructure
- Predictable, low-cost CDN usage
The AWS Setup: Powerful but Heavyweight
With AWS, getting this to work involves a few pieces:
- An S3 bucket to store the files
- CloudFront, AWS’s CDN, to serve those files globally
- SSL certificates from AWS Certificate Manager
- DNS records pointed to the CloudFront distribution
This setup is reliable and backed by plenty of documentation. But it does come with extra complexity, especially when custom domains are involved.
To support a custom domain with SSL on AWS, the user has to:
- Point their domain to our CloudFront distribution
- Add special DNS records to verify ownership of that domain
- Wait for validation and provisioning to complete
This all works, but asking users to handle verification records adds friction. It can be confusing for non-technical users, and it's another support issue we’d have to manage.
The Cloudflare R2 Setup: Fewer Moving Parts
Cloudflare R2 gives us the same basic functionality as S3. It stores files that can be served as a static site. Since hosted.md already runs on Cloudflare, we benefit from deeper integration across services.
When a user publishes a site:
- We upload the files to an R2 bucket
- We can map a subdomain like
yourproject.hosted.md
to that bucket using a couple of DNS changes
- SSL is automatically handled because hosted.md is already part of the Cloudflare platform
There were a few initial configuration tweaks, such as setting rewrite rules to load index.html
files by default. But once that was done, everything clicked into place.
Instant Cache Updates Without Extra Charges
One big advantage of Cloudflare is how it handles caching. When a file is updated, Cloudflare recognizes the change and serves the new version without any extra work on our part.
With AWS, the old version would still be shown unless we manually told CloudFront to "invalidate" the cache. That adds an extra step after each update and also introduces additional costs. AWS actually charges for every invalidation request. If a user publishes frequently or we hit a bug that triggers repeated uploads, those charges could add up quickly.
This wasn’t something we wanted to pass on to users. Nor did we want to constantly monitor or manage cache invalidations ourselves.
Custom Domains and the Proxy Workaround
The one limitation of Cloudflare R2 is when it comes to custom domains. Any domain mapped directly to an R2 bucket needs to be inside the same Cloudflare account. That’s not acceptable, since we can't and shouldn’t ask users to transfer their domains to us.
Our workaround is to use a small proxy server running NGINX. Here’s how that works:
- A user points two DNS records to our proxy server, for example
www.yourdomain.com
and *.yourdomain.com
- We handle the rest, including generating SSL certificates using Let’s Encrypt
This setup keeps the user in control of their domain while still allowing us to serve their site securely with SSL. There is a bit of extra infrastructure on our end, but it’s much easier to maintain than dealing with CloudFront’s configuration and domain validation flow.
A Quick Note on Costs 💸
hosted.md isn’t live yet, so we're still finalizing our pricing. But infrastructure choices like this play a big role in what we’ll eventually be able to offer users.
With AWS, we’d be paying for:
- S3 storage
- CloudFront bandwidth
- Cache invalidation
- SSL and DNS features layered on top
Cloudflare R2 gives us:
- Free cache invalidation
- Lower static file storage costs
- One platform for storage, CDN, DNS, and SSL
That helps keep our costs lower and more predictable. It also allows us to offer a better hosting experience without needing to charge users just to cover infrastructure overhead.
Wrapping Up
Choosing Cloudflare R2 has helped us keep hosted.md lean and maintainable while still giving users the flexibility and performance they expect. The setup is easier to manage and avoids some of the rough edges of AWS, especially for things like custom domain support and file caching.
If you're interested in how this evolves or want to follow along as we continue building hosted.md, keep an eye on the blog or follow along on Bluesky.
More updates soon. 👀