Underrated: Azure Static Website Hosting

Underrated: Azure Static Website Hosting

Adham 7 min read

Most people hear “Azure Storage” and think blobs, backups, logs, archives.

Not frontend platforms.

But Azure Static Website Hosting is one of those underrated tools that can run a serious production frontend for very low cost, with very little ops drama.

In this post, I will show a simple pattern that gives you:

  • full frontend hosting (SPA or static app)
  • safe deployment patterns
  • blue/green style frontend releases
  • controlled rollout percentages (with an edge traffic layer)
  • instant flip between versions when you need rollback

Why This Is Underrated

For many frontend apps, your runtime is just HTML, CSS, JS, images. No server-side rendering needed. No custom runtime needed.

In that case, Azure Storage Static Website gives you:

  • a managed static endpoint
  • a $web container for your assets
  • predictable cost
  • easy automation with the Azure CLI command az storage blob upload-batch

The underrated part is not only the hosting itself. this blog is hosted on Azure, but the real story is how you can use this simple hosting model to do safe blue/green releases without a complex platform.

I will cover some of Blue/Green patterns you can use with Azure blobs.

The Deployment Model

The cleaner pattern is to use one storage account and keep two releases side by side:

  • /releases/a/ (current stable)
  • /releases/b/ (candidate)

Everything is still served from the same static website endpoint.

Release flow:

  1. Build frontend.
  2. Upload one build into /releases/a/ or /releases/b/.
  3. Smoke test that release path directly.
  4. Change one tiny file, or one tiny decision point, to make release A or B active.
  5. If metrics are good, continue to 100%.
  6. If not, flip traffic back in seconds.

This is blue/green deployment for frontend releases, and it is a safe release mechanism.

One-Time Setup (CLI)

Enable static website on the storage account:

az storage blob service-properties update \
  --account-name stmyappsite \
  --static-website \
  --index-document index.html \
  --404-document 404.html

Upload release A into its own folder:

az storage blob upload-batch \
  --source ./dist-a \
  --destination '$web' \
  --destination-path releases/a \
  --account-name stmyappsite \
  --auth-mode login \
  --overwrite

Upload release B into its own folder:

az storage blob upload-batch \
  --source ./dist-b \
  --destination '$web' \
  --destination-path releases/b \
  --account-name stmyappsite \
  --auth-mode login \
  --overwrite

Get the static endpoint for testing:

az storage account show -n stmyappsite -g rg-web --query "primaryEndpoints.web" -o tsv

How You Flip Between Versions

This is the fun part.

Once you have two deployed versions, A and B, the question becomes simple: how do users land on one or the other?

There is more than one good answer.

Main option: same-origin switch inside one storage account

This is the nicest option for this setup.

Keep both releases under the same host:

  • /releases/a/
  • /releases/b/

Then put a tiny file at the root, for example release.json, that says which one is active.

Example:

{
  "active": "b"
}

The root index.html reads that file and redirects the browser to the active release.

<script>
  fetch('/release.json')
    .then(r => r.json())
    .then(cfg => {
      const target = cfg.active === 'b' ? '/releases/b/' : '/releases/a/';
      window.location.replace(target + window.location.search + window.location.hash);
    });
</script>

I like this version because everything stays on the same origin.

No jumping between different storage accounts. No subdomain gymnastics. No cross-origin surprise party.

Rollback is tiny. Change the file from B back to A and you are done.

Option 2: DNS switch

The simple option is DNS.

You can have two storage accounts, one for release A and one for release B. Each has its own static endpoint.

Your public name points to release A today. When you are ready, you update DNS or the mapped endpoint so it points to release B instead.

This works well when:

  • you want a clean blue/green switch
  • you do not need fine-grained percentages
  • you are happy with DNS TTL behavior

This is simple and honest. It is not fancy, but it is reliable.

Option 3: CDN or traffic layer switch

You can have two storage accounts, one for release A and one for release B. Each has its own static endpoint.

If you put a CDN or a traffic layer in front, you can do more interesting rollouts.

For example, you can:

  • send 90% to blue and 10% to green
  • move to 50/50 for a while
  • go all in on green if everything looks good
  • move straight back to blue if something smells funny

Whether that layer is a CDN product, a traffic manager, or any similar edge layer, the idea is the same: keep both versions live and control the percentage outside the app.

Blue/Green Without Overengineering

This is where the setup gets really useful.

You can use the same release A and release B model for different goals:

  • safe releases: B is the new version, A is stable
  • migration: A is old build pipeline, B is new build pipeline

You do not need to jump directly into a giant platform just to get this behavior. One storage account, two release folders, and a switching strategy already get you very far.

Frontend Feature Flags (Separate Concern)

If you later want product experiments, treat them as a separate concern from this deployment model.

This post focuses on blue/green releases at the hosting level:

  1. version switching between release A and release B
  2. rollback safety when a new release has issues

Feature flags can still be useful in app code, but they are not required for this blue/green pattern.

Real-World Guardrails

Some practical points people usually discover the hard way:

  • Static website file names are case-sensitive, Index.html is not index.html.
  • Make sure each release is built with the correct base path, such as /releases/a/ or /releases/b/.
  • If you need custom headers or advanced cache behavior, put a CDN or similar layer in front.
  • DNS flips are simple, but they are not instant in the same way an app-level switch can be.
  • If you switch inside the app, keep the bootstrap file small and boring. That file becomes very important.
  • For production safety, always test /releases/a/ and /releases/b/ directly before changing any routing.

When This Pattern Is a Great Fit

Use this if:

  • your app is static or SPA-heavy
  • you want low-cost hosting
  • you want safe rollout/rollback without a complex platform team

Maybe skip this if you need:

  • built-in auth/authorization at platform layer
  • server-side rendering runtime
  • edge functions tightly coupled to app routing

In those cases, Azure Static Web Apps or App Service may fit better.

Wrapping Up

Azure Static Website Hosting looks basic at first glance. But once you think in terms of parallel releases and traffic control, it becomes much more powerful than people expect.

You can keep things very simple with a DNS switch. You can go one level up with a CDN or traffic layer. Or, my favorite for this article, you can keep both releases in the same storage account and let a tiny file decide whether users go to release A or release B.

That is a lot of control for something that starts as “just a storage account”.

That is exactly why it belongs in the underrated series.

References