And just like that, I was done with Netlify

As someone who uses Netlify’s Starter plan to host this site, the following situation is the kind of nonsense that keeps me up late at night…

On February 24th, an invoice was issued to a Starter plan user of Netlify for a substantial amount of bandwidth usage.

Our internal systems should have identified this rare case, and it should have been flagged by our systems before being sent to this user. We sincerely apologize for this situation and the anxiety it caused. Please know that we are taking this situation very seriously.

This situation has reinforced the urgency of our ongoing work to put safeguards in place in our billing system to ensure that this never happens again. No user of Netlify should ever be concerned that this could happen to them, and we are committed to fixing this issue immediately.

We will also be looking at our company practices, as there clearly was an opportunity for us to have better handled this situation.

Again, we apologize to the impacted user, as well as the community at large. We promise to do better.

Netlify (@Netlify) February 27, 2024

The fact that a small static site hosted for free could potentially cost thousands of dollars is insane. Up until now, I assumed hitting any bandwidth limits would take the site down until the next billing period (or pay any overage fees to turn it back on).

To mitigate the risk of this happening to me, I shut down Netlify deployments and migrated to Cloudflare Pages. On paper Cloudflare’s features are way more attractive and don’t imply free plans will be charged for going over any limits.

Free plan comparison

-CloudflareNetlify
BandwidthUnlimited100GB per month (then $55 per 100GB)
Builds1 concurrent build, 500 times per month1 concurrent build, 300 minutes per month (then $7 per 500)
SitesUnlimited500
Preview deployments
Custom domains100 per project~90 apex domains
SSL certificate
Site analyticsFree$9 per site per month
FilesSites can contain 20,000 files — maximum asset size is 25 MiBLimit of 54,000 files per directory — maximum asset size is 100 MiB
Header rulesMaximum of 100 rules-
RedirectsMaximum of 2,000 static redirects and 100 dynamic redirects. Bulk Redirects allow for much more at the account level.No apparent limit, recommended to keep under 10k redirects
Content scraping protectionProtects text, images and email addresses from web scrapers-
MembersPages site can be managed by an unlimited number of users via the Cloudflare dashboardLimited to 1 free member, with unlimited Git Contributors

Cloudflare Pages

Migrating from Netlify to Cloudflare was painless:

  1. Connect GitHub repository to Cloudflare Pages.
  2. Configure Hugo build command.
  3. Validate *.pages.dev site builds when pushing commits to GitHub.
  4. Copy DNS records from Netlify over to Cloudflare.

The hardest part was waiting for all the records to propagate across the internet.

My custom _headers and _redirects files used by Netlify ported over great too as Cloudflare Pages uses the same.

mademistakes.com Cloudflare Pages build log output

One snag I encountered during the migration was long build times. In my previous workflow, I set up GitHub Actions and Netlify to cache all generated static assets between builds. For a site like mine with thousands of images, this slashes a cold build from 18 minutes down to a minute for incremental builds.

Build cache settings in Cloudflare dashboard.

Cloudflare Pages does support build caching, but only for Gatsby, Next.js, and Astro frameworks. It’s a beta feature, so I expect Hugo to be added in the future. For now I’ll have to live with 18-minute builds — unless I decide to use a GitHub Action again to build then deploy to Cloudflare using their Wrangler CLI. We’ll see…

Cloudflare Web Analytics dashboard showing Core Web Vital scores for mademistakes.com

Another bonus, Cloudflare gives you privacy-first site analytics for free too. Which could be an option if I decide Google Analytics at some point.

And hell, if Cloudflare Pages turns out to be a dud or too restrictive I can always go back to self-hosting on the cheap.

Related

Goodbye Gatsby, Hello Hugo

Hugo has ruined me. Other static site generators that rely on community plugins and copypasta to fill out their gaps don’t cut it anymore…

Jekyll’s site.url and baseurl

Learn what Jekyll’s site url and baseurl variables are and how to properly set them with relative_url and absolute_url filters to avoid broken links and 404 errors.