Azure Blob Storage Pricing

A media company moved 80 TB of backups and video archives into Azure and expected a small monthly bill. Three months later, finance asked why storage costs had tripled. Everything sat in the Hot tier by default. Versioning and soft delete were on for a container that was overwritten nightly. A reporting job also downloaded large files across regions.

Nothing was broken. The team simply never learned how Azure Blob Storage pricing works. The service charges for more than gigabytes, and each setting you choose can move the bill in a different direction.

This guide explains every major cost meter, shows how to pick tiers and redundancy, and gives you commands and templates for a cost-aware storage account. You will also learn how to estimate a bill before you commit and how to find the cause when one spikes.

How Azure Blob Storage Pricing Works

Azure Blob Storage is Microsoft’s object storage service for unstructured data such as documents, images, backups, logs, and data lake files. A storage account is the top-level container that holds your blobs, and most settings that affect cost live there. If you are new to the service, start with the Azure storage account tutorial or the walkthrough to create Azure Blob Storage.

Your bill is the sum of several meters. These are the ones that matter most:

MeterWhat you pay forCommon surprise
Data storageGB stored per month, priced by tier and redundancyDefault Hot tier for everything
OperationsReads, writes, lists, and other requests, billed per 10,000Millions of tiny files
Data retrievalPer GB read from Cool, Cold, and ArchiveReading “cold” data often
Data transferData leaving a region or AzureCross-region copies and downloads
Geo-replication transferCopying data to a secondary regionGRS and GZRS accounts
Early deletionDeleting or moving data before a tier’s minimum periodShort-lived backups in Cool or Archive
Optional featuresSFTP, blob index tags, encryption scopes, change feed, inventorySFTP billed hourly, even when idle

Two points save people money right away. First, uploading data into Azure is not charged, but moving it out is. Second, turning on most features is free, but you pay for the storage and operations those features create. Versioning is a good example. It costs nothing to enable, but every overwrite stores another full copy of the blob.

I am not listing dollar amounts here on purpose. Prices vary by region, redundancy, tier, and whether your account uses a hierarchical namespace. Use the official Azure pricing calculator with your exact settings. For a plain-language view of typical charges, this guide on Azure Blob Storage cost is a helpful companion.

Pro Tip: In my experience, the first cost review should list every meter on the bill, not just the storage line. The total is usually driven by one meter that nobody was watching.

Choose the Right Access Tier

An access tier controls how much you pay to store data versus how much you pay to read it. Colder tiers cost less per GB to store and more to access.

TierBest forMinimum storage periodAccess
HotActive data, websites, processingNoneImmediate
CoolShort-term backups, older reports30 daysImmediate
ColdRarely read data that must stay online90 daysImmediate
ArchiveLong-term compliance retention180 daysOffline, hours to rehydrate

Here is what these differences mean in practice.

Minimum periods are billing rules, not access blocks. You can read Cool or Cold data on day two. But if you delete, overwrite, or move it before the minimum period ends, Azure charges an early deletion fee. The fee is prorated for the remaining days.

Archive is offline. You cannot read an archived blob until you rehydrate it, which means moving it back to Hot, Cool, or Cold. Standard rehydration can take up to about 15 hours, and a high-priority option exists at a higher cost. That is fine for a seven-year compliance archive. It is a bad choice for last night’s database backup, because you may need that restore during an outage.

Archive has a redundancy limit. It works only with accounts that use LRS, GRS, or RA-GRS. Zone-redundant (ZRS, GZRS) accounts do not support it. Check this before you design a lifecycle policy.

The default tier setting is a trap. A general-purpose v2 account has a default access tier of Hot or Cool for blobs without an explicit tier. If you change that default, blobs inheriting it change tier too. Switching to a cooler default triggers write charges for every inherited blob, and switching back to a warmer default triggers read and retrieval charges. On a large account, that can be an expensive afternoon.

Smart Tier and Lifecycle Management

If you do not know your access patterns, consider smart tier. It automatically moves objects between Hot, Cool, and Cold based on how they are used. You pay the normal capacity price for the tier the object sits in, plus a small monitoring fee. You do not pay separate tier-transition, early-deletion, or retrieval charges for those objects.

If your rules are clear, use lifecycle management instead. It is a policy that moves or deletes blobs based on age, last access, or tags. Lifecycle management itself is free, but the transitions are billed as operations. Pick one approach per set of data, because the two features do not manage the same objects together.

Small objects need a second look. Cooler tiers can apply a minimum billable object size, so millions of tiny files may cost more there than in Hot. Check the current pricing page for your account. Packing many small files into larger archives also cuts operation charges.

For a side-by-side look, read this Azure storage account tier comparison.

Pro Tip: I never choose Archive for the newest backups. My rule is simple: keep the last 30 days online, move older chains to Cold, and archive only what the business truly will not need in a hurry.

Redundancy, Region, and Egress Costs

Redundancy decides how many copies of your data Azure keeps and where. Higher redundancy raises the storage price.

  • LRS (locally redundant): Three copies in one datacenter. This is the cheapest option and the weakest against a datacenter failure.
  • ZRS (zone-redundant): Copies across availability zones, which are separate datacenters inside one region. It protects against a zone outage.
  • GRS and GZRS (geo-redundant): Data is also copied to a paired secondary region. This protects against a regional disaster, and it adds geo-replication transfer charges.
  • RA-GRS and RA-GZRS: Same as above, plus read access to the secondary region.

Match redundancy to the data’s value. Production customer files may deserve ZRS or GZRS. A dev container full of test exports does not. Paying for geo-replication on disposable data is one of the most common waste patterns I see.

Region also matters. Prices differ between regions, and data transfer between regions costs money. Keep storage in the same region as the apps and analytics services that read it. This also cuts latency.

Egress (data leaving Azure or crossing regions) is the quiet bill-grower. Ways to control it:

  • Keep compute and storage in the same region.
  • Put a content delivery network in front of public files, so repeated reads hit a cache.
  • Use private connectivity for large internal transfers.
  • Move bulk offline data with Azure Data Box when the network path is slow or expensive.

If you plan to use the account as a data lake, read about Azure Storage account vs. Data Lake Gen2. Hierarchical namespace accounts use different pricing details, including an index meter, and some operations are billed per 4 MB of data.

Pro Tip: I once traced a monthly egress spike to a nightly job running in a different region than the storage account. Moving the job fixed the cost and made it faster.

Build a Cost-Aware Storage Account

Now let’s build a storage account with sensible cost settings. The scenario is an internal document platform. It needs private storage, active files for 30 days, and automatic tiering after that.

Start with a resource group, the container that groups related resources. See how to create a resource group in Azure if you want the portal steps.

az group create \
--name rg-docs-prod \
--location eastus \
--tags owner=it-team costcenter=ops environment=prod

This creates rg-docs-prod in East US. The tags assign an owner and cost center, so cost analysis can split charges by team. See what Azure tags are for naming ideas.

az storage account create \
--name <storage-account-name> \
--resource-group rg-docs-prod \
--location eastus \
--sku Standard_ZRS \
--kind StorageV2 \
--access-tier Hot \
--allow-blob-public-access false \
--min-tls-version TLS1_2 \
--https-only true

Here is why each choice matters:

  • --sku Standard_ZRS copies data across availability zones. It costs more than LRS, but it protects production documents from a datacenter failure.
  • --access-tier Hot sets the default tier for new blobs. Hot suits active files and keeps read costs low.
  • --allow-blob-public-access false blocks anonymous access. Public exposure is both a security risk and a surprise egress risk.
  • --min-tls-version TLS1_2 and --https-only true require modern encrypted connections.

Automate Tiering with a Lifecycle Policy

Save this policy as policy.json. It moves older documents to cooler tiers and removes old versions:

json{
  "rules": [
    {
      "name": "tier-and-clean-docs",
      "enabled": true,
      "type": "Lifecycle",
      "definition": {
        "filters": {
          "blobTypes": ["blockBlob"],
          "prefixMatch": ["documents/"]
        },
        "actions": {
          "baseBlob": {
            "tierToCool": { "daysAfterModificationGreaterThan": 30 },
            "tierToCold": { "daysAfterModificationGreaterThan": 120 }
          },
          "version": {
            "delete": { "daysAfterCreationGreaterThan": 90 }
          }
        }
      }
    }
  ]
}

This rule applies to blobs under the documents/ prefix. It moves them to Cool after 30 days without changes and to Cold after 120 days. It also deletes old versions after 90 days, which stops version storage from growing forever. I left out Archive because this account uses ZRS, and Archive does not support it.

Apply the policy:

az storage account management-policy create \
--account-name <storage-account-name> \
--resource-group rg-docs-prod \
--policy @policy.json

The --policy @policy.json part tells the CLI to read the rule from the file. Policies run on a schedule, usually daily, so changes are not instant. Test the rule on a small prefix first. Warning: delete rules remove data permanently, so confirm the prefix and day counts before you apply them in production.

Repeat It with Bicep

For several environments, use Bicep, Azure’s infrastructure-as-code language. It makes each deployment match the last, so nobody forgets a cost-saving setting.

param storageAccountName string
param location string = resourceGroup().location
param environmentName string = 'prod'
param skuName string = 'Standard_ZRS'

resource storageAccount 'Microsoft.Storage/storageAccounts@2023-01-01' = {
name: storageAccountName
location: location<