<?xml version="1.0" encoding="UTF-8"?>
<rss version="2.0" xmlns:atom="http://www.w3.org/2005/Atom" xmlns:dc="http://purl.org/dc/elements/1.1/">
  <channel>
    <title>DEV Community: Edward Blackhawk</title>
    <description>The latest articles on DEV Community by Edward Blackhawk (@edward_blackhawk).</description>
    <link>https://dev.to/edward_blackhawk</link>
    <image>
      <url>https://media2.dev.to/dynamic/image/width=90,height=90,fit=cover,gravity=auto,format=auto/https:%2F%2Fdev-to-uploads.s3.us-east-2.amazonaws.com%2Fuploads%2Fuser%2Fprofile_image%2F4090897%2F0b000571-1f71-44c9-81a2-e189f59a9ce6.png</url>
      <title>DEV Community: Edward Blackhawk</title>
      <link>https://dev.to/edward_blackhawk</link>
    </image>
    <atom:link rel="self" type="application/rss+xml" href="https://dev.to/feed/edward_blackhawk"/>
    <language>en</language>
    <item>
      <title>40 Hours of Free SQL: Picking a Database on Cloudflare vs Azure as a Solo Founder</title>
      <dc:creator>Edward Blackhawk</dc:creator>
      <pubDate>Tue, 06 Oct 2026 06:51:33 +0000</pubDate>
      <link>https://dev.to/edward_blackhawk/40-hours-of-free-sql-picking-a-database-on-cloudflare-vs-azure-as-a-solo-founder-1ing</link>
      <guid>https://dev.to/edward_blackhawk/40-hours-of-free-sql-picking-a-database-on-cloudflare-vs-azure-as-a-solo-founder-1ing</guid>
      <description>&lt;h1&gt;
  
  
  40 Hours of Free SQL: Picking a Database on Cloudflare vs Azure as a Solo Founder
&lt;/h1&gt;

&lt;p&gt;In my last post I priced the same small project on Cloudflare and Azure, round by round. Azure won the database round in four sentences: deeper toolbox, real PostgreSQL and SQL Server, decades of enterprise tooling.&lt;/p&gt;

&lt;p&gt;That's true. But four sentences is too short for the one decision that's hardest to undo.&lt;/p&gt;

&lt;p&gt;You can move a static site between hosts in an afternoon. You can rewrite a serverless function in a weekend. Your database, on the other hand, holds the schema, the queries, the data and every habit your code formed around them. Whatever you pick in week one is usually what you're still running in year two.&lt;/p&gt;

&lt;p&gt;So this time I asked a narrower question, the one a solo founder actually faces:&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;I need to ship this month. Which database gets me there fastest, costs nothing until it should, and won't trap me later?&lt;/strong&gt;&lt;/p&gt;

&lt;blockquote&gt;
&lt;p&gt;All prices are public list prices in US dollars, checked in October 2026, for US regions (Azure East US). Cloud pricing changes often, so check before you plan a budget around it.&lt;/p&gt;
&lt;/blockquote&gt;

&lt;h2&gt;
  
  
  The menu
&lt;/h2&gt;

&lt;p&gt;Neither platform offers "a database". Each offers a shelf.&lt;/p&gt;

&lt;div class="table-wrapper-paragraph"&gt;&lt;table&gt;
&lt;thead&gt;
&lt;tr&gt;
&lt;th&gt;Need&lt;/th&gt;
&lt;th&gt;Cloudflare&lt;/th&gt;
&lt;th&gt;Azure&lt;/th&gt;
&lt;/tr&gt;
&lt;/thead&gt;
&lt;tbody&gt;
&lt;tr&gt;
&lt;td&gt;Relational, serverless&lt;/td&gt;
&lt;td&gt;
&lt;strong&gt;D1&lt;/strong&gt; (SQLite)&lt;/td&gt;
&lt;td&gt;
&lt;strong&gt;Azure SQL Database&lt;/strong&gt;, serverless tier (SQL Server)&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;Real PostgreSQL / MySQL&lt;/td&gt;
&lt;td&gt;
&lt;strong&gt;Hyperdrive&lt;/strong&gt; in front of any Postgres or MySQL, incl. PlanetScale billed through Cloudflare&lt;/td&gt;
&lt;td&gt;
&lt;strong&gt;Azure Database for PostgreSQL / MySQL&lt;/strong&gt;, Flexible Server&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;Document / NoSQL&lt;/td&gt;
&lt;td&gt;—&lt;/td&gt;
&lt;td&gt;&lt;strong&gt;Cosmos DB&lt;/strong&gt;&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;Key-value&lt;/td&gt;
&lt;td&gt;&lt;strong&gt;Workers KV&lt;/strong&gt;&lt;/td&gt;
&lt;td&gt;Table Storage, Cosmos DB&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;Per-user or per-room state&lt;/td&gt;
&lt;td&gt;
&lt;strong&gt;Durable Objects&lt;/strong&gt; (each with its own SQLite)&lt;/td&gt;
&lt;td&gt;—&lt;/td&gt;
&lt;/tr&gt;
&lt;/tbody&gt;
&lt;/table&gt;&lt;/div&gt;

&lt;p&gt;The headline difference: &lt;strong&gt;Cloudflare doesn't run a Postgres server for you.&lt;/strong&gt; Its relational answer is SQLite (D1), and for anything bigger it gives you a fast pipe (Hyperdrive) to a Postgres that lives somewhere else. Azure runs everything itself.&lt;/p&gt;

&lt;p&gt;For the rest of this post I'll mostly compare the four options a solo founder is likely to start with: &lt;strong&gt;D1&lt;/strong&gt;, &lt;strong&gt;Azure SQL Database&lt;/strong&gt;, &lt;strong&gt;Cosmos DB&lt;/strong&gt; and &lt;strong&gt;Azure PostgreSQL Flexible Server&lt;/strong&gt;.&lt;/p&gt;

&lt;h2&gt;
  
  
  Round 1: Time to first query
&lt;/h2&gt;

&lt;p&gt;This is where "start quickly" is won or lost.&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;Cloudflare D1&lt;/strong&gt; is three steps, and none of them involves a password:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight shell"&gt;&lt;code&gt;npx wrangler d1 create app-db
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;





&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight json-doc"&gt;&lt;code&gt;&lt;span class="c1"&gt;// wrangler.jsonc&lt;/span&gt;&lt;span class="w"&gt;
&lt;/span&gt;&lt;span class="nl"&gt;"d1_databases"&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="p"&gt;[&lt;/span&gt;&lt;span class="w"&gt;
  &lt;/span&gt;&lt;span class="p"&gt;{&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="nl"&gt;"binding"&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="s2"&gt;"DB"&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="nl"&gt;"database_name"&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="s2"&gt;"app-db"&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="nl"&gt;"database_id"&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="s2"&gt;"&amp;lt;id from the command above&amp;gt;"&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="p"&gt;}&lt;/span&gt;&lt;span class="w"&gt;
&lt;/span&gt;&lt;span class="p"&gt;]&lt;/span&gt;&lt;span class="w"&gt;
&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;





&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight typescript"&gt;&lt;code&gt;&lt;span class="kd"&gt;const&lt;/span&gt; &lt;span class="nx"&gt;user&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="k"&gt;await&lt;/span&gt; &lt;span class="nx"&gt;env&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;DB&lt;/span&gt;
  &lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;prepare&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="s2"&gt;SELECT * FROM users WHERE email = ?&lt;/span&gt;&lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;
  &lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;bind&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nx"&gt;email&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;
  &lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;first&lt;/span&gt;&lt;span class="p"&gt;();&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;No connection string, no firewall rule, no secret to rotate, no connection pool to size. &lt;code&gt;wrangler dev&lt;/code&gt; gives you a local copy for development, and &lt;code&gt;wrangler d1 migrations&lt;/code&gt; handles schema changes. The database is a binding, not a network endpoint you have to defend.&lt;/p&gt;

&lt;p&gt;The catch: D1 is built to be used &lt;em&gt;from Workers&lt;/em&gt;. You can reach it from elsewhere over an HTTP API, but if your backend lives on another platform, most of this convenience disappears.&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;Azure SQL Database&lt;/strong&gt; isn't hard, but it's a longer list of decisions:&lt;/p&gt;

&lt;ol&gt;
&lt;li&gt;A resource group.&lt;/li&gt;
&lt;li&gt;A logical server, with an admin login or Microsoft Entra authentication.&lt;/li&gt;
&lt;li&gt;A firewall rule (your IP, plus "allow Azure services" for your app).&lt;/li&gt;
&lt;li&gt;A connection string, stored in app settings or Key Vault.&lt;/li&gt;
&lt;li&gt;A driver (&lt;code&gt;mssql&lt;/code&gt; for Node, or EF Core for .NET).&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;Retry logic.&lt;/strong&gt; Serverless databases pause when idle, and Microsoft's own docs say the first connection after a pause produces &lt;em&gt;predictable&lt;/em&gt; transient errors. You must handle them.&lt;/li&gt;
&lt;/ol&gt;

&lt;p&gt;&lt;strong&gt;PostgreSQL Flexible Server&lt;/strong&gt; is the same shape, plus a networking choice (public access or a private VNet) that you make up front. &lt;strong&gt;Cosmos DB&lt;/strong&gt; asks you to choose a partition key before you write your first document, which is easy to get wrong when you don't know your access patterns yet.&lt;/p&gt;

&lt;p&gt;None of this is unreasonable. It's what running a real database server looks like. But on day one, it's an afternoon on Azure versus ten minutes on Cloudflare.&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;Winner: Cloudflare, as long as your code runs on Workers.&lt;/strong&gt;&lt;/p&gt;

&lt;h2&gt;
  
  
  Round 2: What does "free" actually buy?
&lt;/h2&gt;

&lt;p&gt;Both platforms advertise free databases. They mean very different things.&lt;/p&gt;

&lt;div class="table-wrapper-paragraph"&gt;&lt;table&gt;
&lt;thead&gt;
&lt;tr&gt;
&lt;th&gt;&lt;/th&gt;
&lt;th&gt;Cloudflare D1&lt;/th&gt;
&lt;th&gt;Azure SQL free offer&lt;/th&gt;
&lt;th&gt;Cosmos DB free tier&lt;/th&gt;
&lt;th&gt;Azure PostgreSQL (free account)&lt;/th&gt;
&lt;/tr&gt;
&lt;/thead&gt;
&lt;tbody&gt;
&lt;tr&gt;
&lt;td&gt;How long&lt;/td&gt;
&lt;td&gt;Forever&lt;/td&gt;
&lt;td&gt;Forever&lt;/td&gt;
&lt;td&gt;Forever&lt;/td&gt;
&lt;td&gt;&lt;strong&gt;12 months&lt;/strong&gt;&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;What's free&lt;/td&gt;
&lt;td&gt;5M rows read + 100K rows written &lt;strong&gt;per day&lt;/strong&gt;, 5 GB total&lt;/td&gt;
&lt;td&gt;
&lt;strong&gt;100,000 vCore-seconds&lt;/strong&gt; + 32 GB &lt;strong&gt;per database per month&lt;/strong&gt;, up to 10 databases&lt;/td&gt;
&lt;td&gt;1,000 RU/s + 25 GB, always on&lt;/td&gt;
&lt;td&gt;750 hours of a B1ms server + 32 GB&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;Size limit&lt;/td&gt;
&lt;td&gt;500 MB per database (10 GB on paid)&lt;/td&gt;
&lt;td&gt;32 GB&lt;/td&gt;
&lt;td&gt;25 GB free, then billed&lt;/td&gt;
&lt;td&gt;32 GB free, then billed&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;When you run out&lt;/td&gt;
&lt;td&gt;Queries fail until 00:00 UTC&lt;/td&gt;
&lt;td&gt;
&lt;strong&gt;Database pauses until next month&lt;/strong&gt;, or you opt in to paying&lt;/td&gt;
&lt;td&gt;Billed at normal rates&lt;/td&gt;
&lt;td&gt;Billed at normal rates&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;Catch&lt;/td&gt;
&lt;td&gt;Rows &lt;em&gt;scanned&lt;/em&gt; count, not rows returned&lt;/td&gt;
&lt;td&gt;See below&lt;/td&gt;
&lt;td&gt;One per subscription, opt in at creation only&lt;/td&gt;
&lt;td&gt;Ends after a year&lt;/td&gt;
&lt;/tr&gt;
&lt;/tbody&gt;
&lt;/table&gt;&lt;/div&gt;

&lt;p&gt;The row that surprised me is the Azure SQL one. Let's do the math.&lt;/p&gt;

&lt;h3&gt;
  
  
  The free SQL database that lasts 40 hours
&lt;/h3&gt;

&lt;p&gt;The Azure SQL free offer gives each database 100,000 vCore-seconds of serverless compute per month. That sounds like a lot until you read how serverless is billed.&lt;/p&gt;

&lt;p&gt;While the database is &lt;strong&gt;online&lt;/strong&gt;, Azure bills the maximum of CPU used, memory used, and the minimum you configured, every second. With the default minimum of 0.5 vCores, the matching minimum memory (about 2.1 GB) normalizes to about &lt;strong&gt;0.7 vCores&lt;/strong&gt;. So an online database costs at least 0.7 vCore-seconds per second, even if it's doing nothing.&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;100,000 vCore-seconds ÷ 0.7 ≈ 143,000 seconds ≈ 40 hours
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;&lt;strong&gt;Forty hours of being awake per month.&lt;/strong&gt; It only pauses after it's been idle for the auto-pause delay: 60 minutes by default, 15 at minimum. So:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;If anything touches the database &lt;strong&gt;at least every 15 minutes&lt;/strong&gt; (an uptime monitor, a cron job, a search crawler hitting a page that runs a query), it never pauses. The month's allowance is gone in under two days.&lt;/li&gt;
&lt;li&gt;If traffic comes in bursts, each wake-up costs at least the auto-pause delay: about &lt;strong&gt;40 wake-ups a month&lt;/strong&gt; at the 60-minute default, or about &lt;strong&gt;160&lt;/strong&gt; at 15 minutes.&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;When the allowance runs out, the default is to &lt;strong&gt;pause the database until the first of next month&lt;/strong&gt;. For a production app, that's an outage. The alternative is to keep it online at serverless rates: $0.000145 per vCore-second, which works out to about &lt;strong&gt;$250 a month&lt;/strong&gt; for a database that's always awake at the minimum size.&lt;/p&gt;

&lt;p&gt;To be fair, this offer is excellent for what it's designed for: development, staging, demos and internal tools that sit idle most of the time. It's just not a free production database for an app with steady traffic. If you want cheap Azure SQL in production, the old DTU &lt;strong&gt;Basic&lt;/strong&gt; tier (about $5 a month for a 2 GB database) is the honest option. It's small, but it doesn't pause.&lt;/p&gt;

&lt;h3&gt;
  
  
  The D1 catch: rows scanned, not rows returned
&lt;/h3&gt;

&lt;p&gt;D1 bills &lt;strong&gt;rows read&lt;/strong&gt;, and that means rows &lt;em&gt;scanned&lt;/em&gt;. A query that filters on an unindexed column and returns one row out of 50,000 is billed for 50,000.&lt;/p&gt;

&lt;p&gt;Run that query 100 times and you've used the whole free plan's daily 5M reads. Add the index and the same query reads a handful of rows. Every D1 result includes &lt;code&gt;meta.rows_read&lt;/code&gt;, so log it early and you'll catch this in development, not on your bill.&lt;/p&gt;

&lt;p&gt;The other D1 limit to know before you start: &lt;strong&gt;10 GB per database, hard cap&lt;/strong&gt;, even on the paid plan. D1 is designed for many small databases (one per customer, for instance), not one big one.&lt;/p&gt;

&lt;h3&gt;
  
  
  The quiet winner: Cosmos DB's free tier
&lt;/h3&gt;

&lt;p&gt;Cosmos DB's free tier is the most generous "always on" free database here: &lt;strong&gt;1,000 RU/s of provisioned throughput and 25 GB, for the life of the account.&lt;/strong&gt; It never pauses and never runs out mid-month. As a rough guide, a point read of a 1 KB document costs 1 RU, so that's a lot of headroom for a small app.&lt;/p&gt;

&lt;p&gt;The catches are real, though. You get one free-tier account per subscription, you must turn it on when you create the account, it doesn't work with the serverless option, and Cosmos DB is a document database with a proprietary query model. If you think in tables and joins, you'll fight it.&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;Winner: Cloudflare D1 for a free production database. Cosmos DB if you want NoSQL. Azure SQL's free offer is for dev and staging.&lt;/strong&gt;&lt;/p&gt;

&lt;h2&gt;
  
  
  Round 3: The first real bill
&lt;/h2&gt;

&lt;p&gt;Free tiers end. Here is roughly what the first paid month looks like for a small app with a couple of gigabytes of data and steady traffic throughout the day:&lt;/p&gt;

&lt;div class="table-wrapper-paragraph"&gt;&lt;table&gt;
&lt;thead&gt;
&lt;tr&gt;
&lt;th&gt;Option&lt;/th&gt;
&lt;th&gt;Rough monthly cost&lt;/th&gt;
&lt;th&gt;What you get&lt;/th&gt;
&lt;/tr&gt;
&lt;/thead&gt;
&lt;tbody&gt;
&lt;tr&gt;
&lt;td&gt;Cloudflare D1&lt;/td&gt;
&lt;td&gt;&lt;strong&gt;$5&lt;/strong&gt;&lt;/td&gt;
&lt;td&gt;Workers Paid: 25B rows read, 50M rows written, 5 GB included. The same $5 also covers your Workers.&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;PlanetScale Postgres via Hyperdrive&lt;/td&gt;
&lt;td&gt;&lt;strong&gt;~$5&lt;/strong&gt;&lt;/td&gt;
&lt;td&gt;A single-node Postgres, billable on your Cloudflare invoice. Hyperdrive queries are unlimited on Workers Paid.&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;Cosmos DB free tier&lt;/td&gt;
&lt;td&gt;&lt;strong&gt;$0&lt;/strong&gt;&lt;/td&gt;
&lt;td&gt;As long as you stay within 1,000 RU/s and 25 GB.&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;Azure SQL, DTU Basic&lt;/td&gt;
&lt;td&gt;&lt;strong&gt;~$5&lt;/strong&gt;&lt;/td&gt;
&lt;td&gt;5 DTUs and 2 GB. Small, predictable, always on.&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;Azure PostgreSQL B1ms&lt;/td&gt;
&lt;td&gt;&lt;strong&gt;~$12 + storage&lt;/strong&gt;&lt;/td&gt;
&lt;td&gt;After the first free year. 1 vCPU, 2 GB RAM, real Postgres.&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;Azure SQL serverless, always awake&lt;/td&gt;
&lt;td&gt;&lt;strong&gt;~$250&lt;/strong&gt;&lt;/td&gt;
&lt;td&gt;What the free offer becomes if you choose "continue with charges" and it never pauses.&lt;/td&gt;
&lt;/tr&gt;
&lt;/tbody&gt;
&lt;/table&gt;&lt;/div&gt;

&lt;p&gt;The pattern from my last post shows up again:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;
&lt;strong&gt;Cloudflare bills work.&lt;/strong&gt; Rows read, rows written, gigabytes stored. An idle database costs nothing, and a busy one costs fractions of a cent per million rows.&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;Azure bills time and capacity.&lt;/strong&gt; vCore-seconds while the database is awake, hours a server runs, RU/s you provision. A database that's always reachable is a database that's always billing.&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;Neither is wrong. But for a project that might get ten visitors a day or ten thousand, billing by work is far kinder.&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;Winner: Cloudflare, with Cosmos DB's free tier as a strong exception.&lt;/strong&gt;&lt;/p&gt;

&lt;h2&gt;
  
  
  Round 4: The ceiling, and the way out
&lt;/h2&gt;

&lt;p&gt;Starting quickly is only half the decision. The other half is what happens when you outgrow it, or need to leave.&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;D1 is SQLite.&lt;/strong&gt; That's both its limit and its escape hatch. &lt;code&gt;wrangler d1 export&lt;/code&gt; gives you a plain &lt;code&gt;.sql&lt;/code&gt; file you can load into any SQLite, and with some dialect fixes into Postgres. But the 10 GB per-database cap is real, and each database processes queries one at a time. With 1 ms queries that's about 1,000 per second, which is plenty for most indie apps, but it is a ceiling.&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;Azure PostgreSQL is the most portable choice on this list.&lt;/strong&gt; Postgres runs everywhere, every ORM supports it, and moving it later is a &lt;code&gt;pg_dump&lt;/code&gt; away.&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;Azure SQL is SQL Server.&lt;/strong&gt; That's very portable within the Microsoft world, and great if you live in .NET and EF Core, but less so anywhere else.&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;Cosmos DB has the most lock-in.&lt;/strong&gt; Its native API exists nowhere else. The MongoDB-compatible API helps, but it's still a migration.&lt;/p&gt;

&lt;p&gt;And here's the part that took me longest to notice: &lt;strong&gt;the platforms don't have to match.&lt;/strong&gt; Cloudflare's Hyperdrive will happily sit in front of a Postgres running on Azure. Workers at the edge plus Azure Postgres behind them is a perfectly sensible architecture. You can start on D1, and if you hit the ceiling, move the data to Postgres without moving your app off Workers.&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;Winner: Azure PostgreSQL for portability. D1 as long as you stay under its ceiling.&lt;/strong&gt;&lt;/p&gt;

&lt;h2&gt;
  
  
  Round 5: When you break something
&lt;/h2&gt;

&lt;p&gt;Every solo founder eventually runs &lt;code&gt;DELETE&lt;/code&gt; without a &lt;code&gt;WHERE&lt;/code&gt;.&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;
&lt;strong&gt;D1 Time Travel&lt;/strong&gt; is always on and free: restore to any minute in the last &lt;strong&gt;30 days&lt;/strong&gt; on the paid plan, 7 on free. No setup, no extra cost.&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;Azure SQL&lt;/strong&gt; and &lt;strong&gt;PostgreSQL Flexible Server&lt;/strong&gt; both have automatic backups with point-in-time restore. The Azure SQL free offer limits it to 7 days.&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;Cosmos DB&lt;/strong&gt; takes periodic backups by default. Continuous backup, with point-in-time restore, is an option you choose.&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;All of them will save you. D1 makes it the easiest, because there's nothing to configure in advance.&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;Winner: Cloudflare, narrowly.&lt;/strong&gt;&lt;/p&gt;

&lt;h2&gt;
  
  
  The scorecard
&lt;/h2&gt;

&lt;div class="table-wrapper-paragraph"&gt;&lt;table&gt;
&lt;thead&gt;
&lt;tr&gt;
&lt;th&gt;Round&lt;/th&gt;
&lt;th&gt;Winner&lt;/th&gt;
&lt;/tr&gt;
&lt;/thead&gt;
&lt;tbody&gt;
&lt;tr&gt;
&lt;td&gt;Time to first query&lt;/td&gt;
&lt;td&gt;Cloudflare (on Workers)&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;What "free" buys&lt;/td&gt;
&lt;td&gt;Cloudflare D1 / Cosmos DB free tier&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;The first real bill&lt;/td&gt;
&lt;td&gt;Cloudflare&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;Ceiling and portability&lt;/td&gt;
&lt;td&gt;Azure PostgreSQL&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;Recovery&lt;/td&gt;
&lt;td&gt;Cloudflare, narrowly&lt;/td&gt;
&lt;/tr&gt;
&lt;/tbody&gt;
&lt;/table&gt;&lt;/div&gt;

&lt;h2&gt;
  
  
  My short version
&lt;/h2&gt;

&lt;p&gt;If I were starting a new project tomorrow:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;
&lt;strong&gt;My app runs on Workers and the data is relational:&lt;/strong&gt; D1. Index everything I filter on, and log &lt;code&gt;rows_read&lt;/code&gt; from day one.&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;I need real Postgres&lt;/strong&gt; (extensions, an ORM that expects it, or data that will clearly exceed 10 GB): Postgres from the start, either Azure Flexible Server or PlanetScale through Hyperdrive.&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;I'm already deep in .NET and Azure:&lt;/strong&gt; Azure SQL, but on the Basic or provisioned tier for production. Keep the free offer for staging.&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;My data really is documents and my throughput is predictable:&lt;/strong&gt; Cosmos DB with the free tier switched on at creation.&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;I'm unsure:&lt;/strong&gt; D1. It's the cheapest to try and the easiest to export from. Moving SQLite to Postgres later is a weekend; moving off a document store is a project.&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;Or, in one line:&lt;/p&gt;

&lt;blockquote&gt;
&lt;p&gt;&lt;strong&gt;Azure's free databases give you time. Cloudflare's give you work.&lt;/strong&gt; For a solo founder with unpredictable traffic, work is the better deal.&lt;/p&gt;
&lt;/blockquote&gt;

&lt;h2&gt;
  
  
  Where this is going
&lt;/h2&gt;

&lt;p&gt;I have two projects to decide on:&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;&lt;a href="https://quickprepmedia.com" rel="noopener noreferrer"&gt;Media tools for creators&lt;/a&gt;&lt;/strong&gt; and &lt;strong&gt;&lt;em&gt;&lt;a href="https://deyevibe.com" rel="noopener noreferrer"&gt;What to do in your city&lt;/a&gt;&lt;/em&gt;&lt;/strong&gt; &lt;/p&gt;

&lt;p&gt;Both will need a database eventually. Accounts, saved favorites, reviews, a creator's presets synced across devices: the moment one of those features ships, this post stops being research and becomes a decision.&lt;/p&gt;

&lt;p&gt;When that happens, I'll write up which one I picked and whether the numbers above survived contact with real users.&lt;/p&gt;

&lt;p&gt;Until then: &lt;strong&gt;what are you running, and what surprised you on your first real bill?&lt;/strong&gt; I'd love to hear it in the comments, especially if you've hit the D1 ceiling or the Azure SQL free limit in production.&lt;/p&gt;

</description>
      <category>cloudflare</category>
      <category>azure</category>
      <category>webdev</category>
      <category>database</category>
    </item>
    <item>
      <title>Same Terabyte, $0 to $205: Cloudflare vs Azure for a Solo Developer</title>
      <dc:creator>Edward Blackhawk</dc:creator>
      <pubDate>Mon, 28 Sep 2026 06:12:48 +0000</pubDate>
      <link>https://dev.to/edward_blackhawk/same-terabyte-0-to-205-cloudflare-vs-azure-for-a-solo-developer-gm4</link>
      <guid>https://dev.to/edward_blackhawk/same-terabyte-0-to-205-cloudflare-vs-azure-for-a-solo-developer-gm4</guid>
      <description>&lt;p&gt;In my last post I described how Azure trapped a custom domain, a web app and an entire resource group in a state I couldn't delete, and how I ended up moving that project to Cloudflare Workers.&lt;/p&gt;

&lt;p&gt;A few people asked a fair question: &lt;em&gt;was that just a bad afternoon, or is one platform actually a better deal?&lt;/em&gt;&lt;/p&gt;

&lt;p&gt;So I sat down with both price lists and asked the question every solo developer eventually has to ask: &lt;strong&gt;what would the same project cost on each?&lt;/strong&gt;&lt;/p&gt;

&lt;p&gt;The answer surprised me. It isn't really about who has the bigger free tier. It's about &lt;strong&gt;what each platform decides to charge you for.&lt;/strong&gt;&lt;/p&gt;

&lt;blockquote&gt;
&lt;p&gt;All prices below are public list prices in US dollars, checked in September 2026, for US regions (Azure East US / Zone 1). Cloud pricing changes often, so verify before you plan a budget around it.&lt;/p&gt;
&lt;/blockquote&gt;

&lt;h2&gt;
  
  
  Round 1: Static hosting and bandwidth
&lt;/h2&gt;

&lt;p&gt;This is the round that matters most for a typical indie project: a static or mostly static site, a few assets, and traffic you hope will grow.&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;Cloudflare Workers (static assets)&lt;/strong&gt;&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;Requests to static assets are free and unlimited, on both the free and paid plans.&lt;/li&gt;
&lt;li&gt;There is no bandwidth line on the bill.&lt;/li&gt;
&lt;li&gt;CDN, DNS, TLS and unmetered DDoS protection come with the free plan.&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;&lt;strong&gt;Azure&lt;/strong&gt;&lt;/p&gt;

&lt;p&gt;There are several ways to serve a static site on Azure, and each one bills bandwidth differently:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;
&lt;strong&gt;Static Web Apps, Free plan&lt;/strong&gt;: $0, 100 GB of bandwidth per subscription, no overage. Beyond that, you upgrade.&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;Static Web Apps, Standard plan&lt;/strong&gt;: $9 per app per month, 100 GB included, then &lt;strong&gt;$0.20 per GB&lt;/strong&gt;.&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;Blob Storage static website&lt;/strong&gt; (no CDN): the first 100 GB of internet egress per month is free, then about &lt;strong&gt;$0.087 per GB&lt;/strong&gt;.&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;Front Door Standard&lt;/strong&gt; (Azure's CDN): &lt;strong&gt;$35 per month&lt;/strong&gt; base fee plus about &lt;strong&gt;$0.17 per GB&lt;/strong&gt; for the first 10 TB, plus request fees.&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;Here is what that looks like for the same site at three traffic levels:&lt;/p&gt;

&lt;div class="table-wrapper-paragraph"&gt;&lt;table&gt;
&lt;thead&gt;
&lt;tr&gt;
&lt;th&gt;Monthly traffic&lt;/th&gt;
&lt;th&gt;Cloudflare Workers&lt;/th&gt;
&lt;th&gt;Azure SWA Standard&lt;/th&gt;
&lt;th&gt;Azure Blob (direct)&lt;/th&gt;
&lt;th&gt;Azure Front Door Std&lt;/th&gt;
&lt;/tr&gt;
&lt;/thead&gt;
&lt;tbody&gt;
&lt;tr&gt;
&lt;td&gt;100 GB&lt;/td&gt;
&lt;td&gt;&lt;strong&gt;$0&lt;/strong&gt;&lt;/td&gt;
&lt;td&gt;$9 (or $0 on Free)&lt;/td&gt;
&lt;td&gt;$0&lt;/td&gt;
&lt;td&gt;~$52&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;1 TB&lt;/td&gt;
&lt;td&gt;&lt;strong&gt;$0&lt;/strong&gt;&lt;/td&gt;
&lt;td&gt;$189&lt;/td&gt;
&lt;td&gt;~$78&lt;/td&gt;
&lt;td&gt;~$205&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;10 TB&lt;/td&gt;
&lt;td&gt;&lt;strong&gt;$0&lt;/strong&gt;&lt;/td&gt;
&lt;td&gt;~$1,989&lt;/td&gt;
&lt;td&gt;~$861&lt;/td&gt;
&lt;td&gt;~$1,735&lt;/td&gt;
&lt;/tr&gt;
&lt;/tbody&gt;
&lt;/table&gt;&lt;/div&gt;

&lt;p&gt;That is the headline result: &lt;strong&gt;the same terabyte of HTML, CSS and JavaScript costs anywhere from $0 to about $205 a month, depending on which door it leaves through.&lt;/strong&gt;&lt;/p&gt;

&lt;p&gt;One honest caveat: Cloudflare's generosity is for ordinary web pages and assets. If you want to serve a video library, its terms steer you toward its paid media products. For a site full of calculators, blog posts and images, it doesn't come up.&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;Winner: Cloudflare, by a mile.&lt;/strong&gt;&lt;/p&gt;

&lt;h2&gt;
  
  
  Round 2: Serverless compute
&lt;/h2&gt;

&lt;p&gt;This round is closer, and it's where the difference in billing philosophy shows up most clearly.&lt;/p&gt;

&lt;div class="table-wrapper-paragraph"&gt;&lt;table&gt;
&lt;thead&gt;
&lt;tr&gt;
&lt;th&gt;&lt;/th&gt;
&lt;th&gt;Cloudflare Workers&lt;/th&gt;
&lt;th&gt;Azure Functions (Flex Consumption)&lt;/th&gt;
&lt;/tr&gt;
&lt;/thead&gt;
&lt;tbody&gt;
&lt;tr&gt;
&lt;td&gt;Free allowance&lt;/td&gt;
&lt;td&gt;100,000 requests per day&lt;/td&gt;
&lt;td&gt;250,000 executions + 100,000 GB-s per month&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;Paid entry point&lt;/td&gt;
&lt;td&gt;$5/month minimum&lt;/td&gt;
&lt;td&gt;Pay per use, no minimum&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;Included in paid&lt;/td&gt;
&lt;td&gt;10M requests + 30M CPU-ms per month&lt;/td&gt;
&lt;td&gt;—&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;Requests&lt;/td&gt;
&lt;td&gt;$0.30 per million after that&lt;/td&gt;
&lt;td&gt;$0.40 per million&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;Compute&lt;/td&gt;
&lt;td&gt;$0.02 per million &lt;strong&gt;CPU milliseconds&lt;/strong&gt;
&lt;/td&gt;
&lt;td&gt;$0.000026 per &lt;strong&gt;GB-second&lt;/strong&gt; of instance memory&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;Memory&lt;/td&gt;
&lt;td&gt;128 MB&lt;/td&gt;
&lt;td&gt;512 MB, 2 GB or 4 GB instances&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;Max run time&lt;/td&gt;
&lt;td&gt;30 s CPU by default, up to 5 min&lt;/td&gt;
&lt;td&gt;Much longer; built for heavier jobs&lt;/td&gt;
&lt;/tr&gt;
&lt;/tbody&gt;
&lt;/table&gt;&lt;/div&gt;

&lt;p&gt;The most important line is the compute row.&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;Cloudflare bills CPU time.&lt;/strong&gt; If your function waits 200 ms for a database and does 3 ms of real work, you pay for 3 ms. Waiting is free.&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;Azure bills memory × wall-clock time.&lt;/strong&gt; On Flex Consumption, you pay for the instance's configured memory while it is executing, with a minimum billable period of one second. Waiting on a database costs the same as calculating.&lt;/p&gt;

&lt;p&gt;For the typical indie API — mostly glue code, mostly waiting on something else — Cloudflare's model works in your favor. For heavy, long-running jobs that need gigabytes of memory, Workers simply isn't the right tool, and Azure is.&lt;/p&gt;

&lt;p&gt;Two other details are worth knowing:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;
&lt;strong&gt;Cold starts.&lt;/strong&gt; Workers run in V8 isolates that start in milliseconds. Azure's on-demand instances can cold-start, and the fix is Flex Consumption's &lt;em&gt;always-ready&lt;/em&gt; instances.&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;A funny coincidence.&lt;/strong&gt; Keeping one 512 MB Flex instance always ready costs about &lt;strong&gt;$5.26 a month&lt;/strong&gt; in baseline fees. That is almost exactly the $5 Workers Paid minimum. Both platforms end up charging about five dollars a month to stay awake.&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;Also, if you're still on Azure's classic &lt;strong&gt;Consumption&lt;/strong&gt; plan, it is now labeled &lt;em&gt;legacy&lt;/em&gt;, and the Linux version retires on 30 September 2028. The cheaper numbers you may remember ($0.20 per million executions, 1M free per month) belong to that plan.&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;Winner: Cloudflare for light, I/O-bound APIs. Azure for anything heavy.&lt;/strong&gt;&lt;/p&gt;

&lt;h2&gt;
  
  
  Round 3: Object storage
&lt;/h2&gt;

&lt;div class="table-wrapper-paragraph"&gt;&lt;table&gt;
&lt;thead&gt;
&lt;tr&gt;
&lt;th&gt;&lt;/th&gt;
&lt;th&gt;Cloudflare R2&lt;/th&gt;
&lt;th&gt;Azure Blob (Hot, LRS)&lt;/th&gt;
&lt;/tr&gt;
&lt;/thead&gt;
&lt;tbody&gt;
&lt;tr&gt;
&lt;td&gt;Storage&lt;/td&gt;
&lt;td&gt;$0.015 / GB-month&lt;/td&gt;
&lt;td&gt;~$0.021 / GB-month&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;Free tier&lt;/td&gt;
&lt;td&gt;10 GB, 1M writes, 10M reads per month&lt;/td&gt;
&lt;td&gt;—&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;Egress to the internet&lt;/td&gt;
&lt;td&gt;&lt;strong&gt;Free&lt;/strong&gt;&lt;/td&gt;
&lt;td&gt;~$0.087 / GB after 100 GB&lt;/td&gt;
&lt;/tr&gt;
&lt;/tbody&gt;
&lt;/table&gt;&lt;/div&gt;

&lt;p&gt;Storage is roughly comparable. Egress is where things diverge. R2 was designed around zero egress fees, and for anything users download, that dominates the bill.&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;Winner: Cloudflare.&lt;/strong&gt;&lt;/p&gt;

&lt;h2&gt;
  
  
  Round 4: Databases
&lt;/h2&gt;

&lt;p&gt;This is where Azure wins.&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;
&lt;strong&gt;Cloudflare D1&lt;/strong&gt; is SQLite at the edge. The free plan includes 5M rows read and 100K rows written per day, plus 5 GB of storage. It's lovely for small apps, but it is still SQLite.&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;Azure Cosmos DB&lt;/strong&gt; has a lifetime free tier with 1,000 RU/s and 25 GB per subscription. And beyond that, Azure offers the full range of managed PostgreSQL, SQL Server, Redis and more, with backups, replicas and decades of enterprise tooling.&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;If your project is really a database with a website attached, Azure has a far deeper toolbox.&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;Winner: Azure.&lt;/strong&gt;&lt;/p&gt;

&lt;h2&gt;
  
  
  Round 5: Everything heavy
&lt;/h2&gt;

&lt;p&gt;VMs, containers with real memory, GPUs, long batch jobs, private networking, Entra ID, compliance certifications, sixty-plus regions to pin data to, first-class Windows and .NET. This is Azure's home ground, and Cloudflare isn't really competing for it.&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;Winner: Azure.&lt;/strong&gt;&lt;/p&gt;

&lt;h2&gt;
  
  
  Round 6: When something breaks
&lt;/h2&gt;

&lt;p&gt;This round is why I wrote the first post.&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;
&lt;strong&gt;Azure's Basic plan&lt;/strong&gt; is included for everyone, but it doesn't include technical support. Paid plans start at &lt;strong&gt;$29 a month&lt;/strong&gt; (Developer), and 24/7 technical support starts at $100.&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;Cloudflare's free plan&lt;/strong&gt; also means community support. Nobody gives you a free engineer.&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;So neither platform wins on paper. The real difference is how often you end up needing that engineer, and my experience with Azure's custom-domain setup is exactly the failure case you hope never to face.&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;Winner: Draw, with an asterisk.&lt;/strong&gt;&lt;/p&gt;

&lt;h2&gt;
  
  
  The scorecard
&lt;/h2&gt;

&lt;div class="table-wrapper-paragraph"&gt;&lt;table&gt;
&lt;thead&gt;
&lt;tr&gt;
&lt;th&gt;Round&lt;/th&gt;
&lt;th&gt;Winner&lt;/th&gt;
&lt;/tr&gt;
&lt;/thead&gt;
&lt;tbody&gt;
&lt;tr&gt;
&lt;td&gt;Static hosting &amp;amp; bandwidth&lt;/td&gt;
&lt;td&gt;Cloudflare&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;Serverless compute&lt;/td&gt;
&lt;td&gt;Cloudflare (light) / Azure (heavy)&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;Object storage&lt;/td&gt;
&lt;td&gt;Cloudflare&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;Databases&lt;/td&gt;
&lt;td&gt;Azure&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;Everything heavy&lt;/td&gt;
&lt;td&gt;Azure&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;Support&lt;/td&gt;
&lt;td&gt;Draw&lt;/td&gt;
&lt;/tr&gt;
&lt;/tbody&gt;
&lt;/table&gt;&lt;/div&gt;

&lt;h2&gt;
  
  
  The interesting result
&lt;/h2&gt;

&lt;p&gt;Once I lined everything up, I noticed a pattern I hadn't expected.&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;Azure bills you for what you reserve and what leaves its network&lt;/strong&gt;: memory-seconds, provisioned instances and every gigabyte your users download.&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;Cloudflare bills you for work&lt;/strong&gt;: requests and CPU milliseconds. Bandwidth, the thing that grows fastest when a small project succeeds, is mostly off the bill.&lt;/p&gt;

&lt;p&gt;That changes what "scaling" means financially:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;On Azure, your bill grows with &lt;strong&gt;how popular you are&lt;/strong&gt;.&lt;/li&gt;
&lt;li&gt;On Cloudflare, your bill grows with &lt;strong&gt;how much your code does&lt;/strong&gt;.&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;For a solo developer shipping lightweight tools, that second model is almost unfair. A post that hits the front page of Hacker News costs you nothing extra. On Azure, the same spike arrives as an egress line item.&lt;/p&gt;

&lt;p&gt;But flip the project around (heavy compute, a serious relational database, enterprise customers asking about compliance) and the scorecard flips with it.&lt;/p&gt;

&lt;p&gt;My short version:&lt;/p&gt;

&lt;blockquote&gt;
&lt;p&gt;&lt;strong&gt;Cloudflare wins the rounds a solo developer fights every month. Azure wins the rounds a company fights once a quarter.&lt;/strong&gt;&lt;/p&gt;
&lt;/blockquote&gt;

&lt;h2&gt;
  
  
  Now, a little game
&lt;/h2&gt;

&lt;p&gt;I run two small projects, both free and both running entirely in your browser:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;
&lt;strong&gt;&lt;a href="https://handymantoolkits.com/en" rel="noopener noreferrer"&gt;Handyman Toolkits&lt;/a&gt;&lt;/strong&gt;: construction and home-improvement calculators (concrete, lumber, drywall, roofing and more).&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;&lt;a href="https://quickprepmedia.com" rel="noopener noreferrer"&gt;QuickPrepMedia&lt;/a&gt;&lt;/strong&gt;: privacy-first media tools for creators. One click, one result, and your files never leave your device.&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;&lt;strong&gt;One runs on Azure. The other runs on Cloudflare.&lt;/strong&gt;&lt;/p&gt;

&lt;p&gt;Open both, click around, and tell me in the comments which one is which. Go by how they &lt;em&gt;feel&lt;/em&gt;: first load, navigation, how quickly things respond.&lt;/p&gt;

&lt;p&gt;Two rules:&lt;/p&gt;

&lt;ol&gt;
&lt;li&gt;No &lt;code&gt;curl -I&lt;/code&gt;, no DevTools response headers, no DNS lookups. That's cheating.&lt;/li&gt;
&lt;li&gt;If you read my previous post, you already have half the answer. Please keep it out of the comments.&lt;/li&gt;
&lt;/ol&gt;

</description>
      <category>webdev</category>
      <category>programming</category>
      <category>productivity</category>
      <category>architecture</category>
    </item>
    <item>
      <title>The Azure Portal Trapped My Domain and Resource Group in Deletion Limbo</title>
      <dc:creator>Edward Blackhawk</dc:creator>
      <pubDate>Sun, 23 Aug 2026 14:38:22 +0000</pubDate>
      <link>https://dev.to/edward_blackhawk/the-azure-portal-trapped-my-domain-and-resource-group-in-deletion-limbo-171f</link>
      <guid>https://dev.to/edward_blackhawk/the-azure-portal-trapped-my-domain-and-resource-group-in-deletion-limbo-171f</guid>
      <description>&lt;p&gt;I'm a solopreneur. That means every hour spent wrestling with infrastructure is an hour I'm not spending on the product.&lt;/p&gt;

&lt;p&gt;Recently, I decided to deploy one of my projects to Azure. The initial setup went smoothly: the application was online, the deployment worked, and everything looked ready to go.&lt;/p&gt;

&lt;p&gt;Then I tried to connect my custom domain.&lt;/p&gt;

&lt;p&gt;That was where the trouble started.&lt;/p&gt;

&lt;h2&gt;
  
  
  The custom domain that became stuck
&lt;/h2&gt;

&lt;p&gt;I had registered the domain with another provider and wanted to connect it to my Azure-hosted application. The process failed—but not cleanly.&lt;/p&gt;

&lt;p&gt;Azure appeared to leave the domain configuration in a broken intermediate state. I couldn't complete the connection, and I couldn't remove it to start again.&lt;/p&gt;

&lt;p&gt;I was effectively stuck with a resource that Azure had failed to create properly but still refused to delete.&lt;/p&gt;

&lt;p&gt;After spending too much time retrying the same operations through the web interface, I decided to remove the entire resource group and rebuild everything from scratch.&lt;/p&gt;

&lt;p&gt;That failed too.&lt;/p&gt;

&lt;h2&gt;
  
  
  Even the resource group wouldn't delete
&lt;/h2&gt;

&lt;p&gt;Deleting the resource group should have been the nuclear option: remove the application and everything associated with it, then start over.&lt;/p&gt;

&lt;p&gt;Instead, the deletion became stuck.&lt;/p&gt;

&lt;p&gt;At this point, I had:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;A custom domain that hadn't connected&lt;/li&gt;
&lt;li&gt;A domain configuration I couldn't remove&lt;/li&gt;
&lt;li&gt;A resource group I couldn't delete&lt;/li&gt;
&lt;li&gt;No useful explanation in the Azure portal&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;For a solo developer, this is particularly frustrating. There isn't an infrastructure team to hand the problem to. You are the developer, DevOps engineer, support desk, and customer—all at the same time.&lt;/p&gt;

&lt;h2&gt;
  
  
  “Please pay us to investigate”
&lt;/h2&gt;

&lt;p&gt;Eventually, I tried contacting Azure support.&lt;/p&gt;

&lt;p&gt;The support path I reached required a paid technical-support plan to investigate the problem.&lt;/p&gt;

&lt;p&gt;That was the moment the situation became almost funny: the platform had created a state its own interface couldn't resolve, and I was apparently expected to pay to learn why.&lt;/p&gt;

&lt;p&gt;I understand charging for consulting, architecture guidance, or hands-on engineering support. But paying to resolve what looked like a platform bug—or at least a failure mode with no actionable error message—felt very different.&lt;/p&gt;

&lt;p&gt;So I went back to debugging it myself.&lt;/p&gt;

&lt;h2&gt;
  
  
  An AI agent helped trace the dependency
&lt;/h2&gt;

&lt;p&gt;I used an AI coding agent alongside the command-line tools to inspect the Azure resources and track the failed deletion.&lt;/p&gt;

&lt;p&gt;The important discovery was that, in my particular configuration, the web app had to be removed before the resource group deletion could finish. The portal had not made that dependency clear, and its attempt to delete the app had also failed.&lt;/p&gt;

&lt;p&gt;I repeated the operation from the command line, removed the application first, and then deleted the resource group.&lt;/p&gt;

&lt;p&gt;This time, it worked.&lt;/p&gt;

&lt;p&gt;The infrastructure was finally gone.&lt;/p&gt;

&lt;p&gt;To be clear, “delete the app before deleting the resource group” should not be treated as a universal Azure rule. It was the dependency blocking my setup. The real problem was that the portal neither resolved it nor explained it clearly enough for me to act.&lt;/p&gt;

&lt;h2&gt;
  
  
  Why I moved to Cloudflare Workers
&lt;/h2&gt;

&lt;p&gt;After that experience, I moved the project to Cloudflare Workers.&lt;/p&gt;

&lt;p&gt;So far, the deployment has been straightforward, the domain configuration has worked, and I've spent more time on the product than on the hosting platform.&lt;/p&gt;

&lt;p&gt;Will it remain painless forever? Probably not. Every platform has limits, bugs, and awkward edge cases. I'm not claiming that Cloudflare Workers is automatically the right choice for every application.&lt;/p&gt;

&lt;p&gt;But for a small, mostly client-side project run by one person, reducing operational friction matters enormously.&lt;/p&gt;

&lt;p&gt;The project is &lt;a href="https://handymantoolkits.com/en" rel="noopener noreferrer"&gt;Handyman Toolkits&lt;/a&gt;, a collection of browser-based construction and home-improvement calculators. Feel free to poke around—and let me know if you manage to break something.&lt;/p&gt;

&lt;h2&gt;
  
  
  What I learned
&lt;/h2&gt;

&lt;p&gt;A few lessons came out of the experience:&lt;/p&gt;

&lt;ol&gt;
&lt;li&gt;&lt;p&gt;&lt;strong&gt;A friendly dashboard is not a substitute for observable infrastructure.&lt;/strong&gt; When the UI fails, you still need a way to inspect the actual resource state.&lt;/p&gt;&lt;/li&gt;
&lt;li&gt;&lt;p&gt;&lt;strong&gt;Learn the command-line escape hatch early.&lt;/strong&gt; Don't wait until the portal leaves a resource stuck.&lt;/p&gt;&lt;/li&gt;
&lt;li&gt;&lt;p&gt;&lt;strong&gt;Deletion order can matter.&lt;/strong&gt; If a resource group won't disappear, inspect the resources and dependencies inside it instead of repeatedly clicking Delete.&lt;/p&gt;&lt;/li&gt;
&lt;li&gt;&lt;p&gt;&lt;strong&gt;Support pricing affects platform choice.&lt;/strong&gt; For a larger company, a paid support plan may be routine. For a bootstrapped solo project, it can change the economics completely.&lt;/p&gt;&lt;/li&gt;
&lt;li&gt;&lt;p&gt;&lt;strong&gt;Developer experience includes failure recovery.&lt;/strong&gt; A platform isn't easy to use only because the happy path is polished. What matters just as much is what happens when something breaks.&lt;/p&gt;&lt;/li&gt;
&lt;/ol&gt;

&lt;p&gt;Azure got my application online quickly. But when one domain operation failed, recovering from it took far more effort than the original deployment.&lt;/p&gt;

&lt;p&gt;That experience was enough to make me try something else.&lt;/p&gt;

&lt;p&gt;Cloudflare Workers is going well so far—but we'll see.&lt;/p&gt;

&lt;p&gt;Curious if you had some similar issues...&lt;/p&gt;

</description>
      <category>azure</category>
      <category>cloudflare</category>
      <category>solopreneur</category>
      <category>devops</category>
    </item>
  </channel>
</rss>
