Home / Azure

AzureHow-toIntermediate

Optimization: Blob Storage lifecycle management and access tiers without surprise charges

Storage accounts keep everything in the Hot tier forever by default. Find what data is old and cold, write lifecycle rules that move blobs through Cool, Cold and Archive and delete what's no longer needed, and avoid the traps of early-deletion fees, rehydration delays and transaction costs.

Deepak Bhardwaj4 min read

Applies toAzure Blob Storage and Data Lake Storage Gen2 (general-purpose v2 accounts), lifecycle management policies, blob inventory

Tiers in one table

Tier Storage price Access cost Minimum days (early deletion charge) Access
Hot Highest Lowest None Immediate
Cool Lower Higher 30 Immediate
Cold Lower still Higher still 90 Immediate
Archive Lowest Highest + rehydration 180 Offline: rehydrate first (hours)

Check current prices for your region and redundancy. The point: colder tiers trade cheap storage for expensive reads.

1. Know your data

Turn on blob inventory (daily or weekly CSV/Parquet report) and query it:

-- e.g. with Synapse serverless / Databricks / DuckDB over the inventory files
SELECT split_part(Name, '/', 1) AS top_folder, AccessTier,
       COUNT(*) AS blobs, SUM("Content-Length") / 1e12 AS TB,
       MIN("Last-Modified") AS oldest
FROM inventory
GROUP BY 1, 2 ORDER BY TB DESC;

Questions to answer per container/prefix: how big, how old, how often read (storage account read transaction metrics by API, or last-access tracking), and does a retention requirement exist?

2. Enable last-access tracking (optional)

az storage account blob-service-properties update -g rg-data --account-name stlogs01 \
  --enable-last-access-tracking true

Rules can then use daysAfterLastAccessTimeGreaterThan, which is useful when "old" doesn't mean "unused". Last access updates are recorded at most once per 24 hours.

3. Write the lifecycle policy

{
  "rules": [
    {
      "name": "app-logs",
      "enabled": true,
      "type": "Lifecycle",
      "definition": {
        "filters": { "blobTypes": ["blockBlob"], "prefixMatch": ["logs/"] },
        "actions": {
          "baseBlob": {
            "tierToCool":    { "daysAfterModificationGreaterThan": 30 },
            "tierToCold":    { "daysAfterModificationGreaterThan": 90 },
            "delete":        { "daysAfterModificationGreaterThan": 400 }
          },
          "snapshot": { "delete": { "daysAfterCreationGreaterThan": 90 } },
          "version":  { "delete": { "daysAfterCreationGreaterThan": 90 } }
        }
      }
    },
    {
      "name": "exports-archive",
      "enabled": true,
      "type": "Lifecycle",
      "definition": {
        "filters": { "blobTypes": ["blockBlob"], "prefixMatch": ["exports/yearly/"] },
        "actions": { "baseBlob": { "tierToArchive": { "daysAfterModificationGreaterThan": 180 } } }
      }
    }
  ]
}
az storage account management-policy create -g rg-data --account-name stlogs01 --policy @policy.json

The policy runs in the background (typically once a day). The first run on a large account can take a while.

4. Avoid the traps

Trap Avoid by
Early deletion fees Don't delete/move blobs before the tier's minimum days
Archive reads take hours Archive only data you can wait for; test a rehydration
Many tiny blobs Per-blob transaction cost of tier changes can exceed savings; pack small files (zip/parquet) first
Versions and snapshots grow silently Include version and snapshot actions
Cool data read daily Reads cost more than you save; check read metrics first
Archive isn't available on ZRS, GZRS or RA-GZRS accounts Check the account's redundancy before planning archive rules

5. Set the default tier sensibly

For accounts that mostly receive write-once data (backups, exports), set the account default access tier to Cool, or upload directly to a tier:

az storage blob upload --account-name stexports01 -c exports -n 2026/10/data.parquet -f data.parquet --tier Cold --auth-mode login

6. Clean up what isn't data

  • Incomplete uploads and abandoned containers from old projects.
  • Soft-deleted blobs retained longer than needed (soft delete retention is a setting).
  • Old diagnostic containers (insights-logs-*) in accounts that also go to Log Analytics.

7. Measure

Track capacity per tier (BlobCapacity metric split by Tier) and the storage line in Cost Management monthly. Expect savings to show up gradually as rules move data.

Caution

Lifecycle delete actions are permanent once soft delete retention passes. Review prefixes with the data owner and start with tiering-only rules; add delete after a cycle of observation.

Checklist

  • Blob inventory reviewed by prefix, age and tier
  • Retention requirements confirmed with owners
  • Lifecycle rules for base blobs, versions, snapshots
  • Small-file and read-frequency traps checked
  • Default tiers set for write-once accounts
  • Capacity per tier tracked monthly