Access Tiers — Hot, Cool, Cold, Archive

Overview

Azure Blob Storage offers four access tiers that let you balance storage costs against access costs. Data that is accessed frequently should live in a higher-cost, lower-latency tier, while data that is rarely accessed can be stored cheaply in a lower tier with higher retrieval costs.

Choosing the right tier — and automating transitions between tiers — is one of the most impactful cost optimization strategies for storage-heavy workloads.


Understanding the Four Tiers

Hot Tier

  • Purpose: Data that is accessed or modified frequently
  • Latency: Milliseconds (same as standard blob access)
  • Minimum storage duration: None
  • Use cases: Active application data, web content, recently uploaded files, databases

Cool Tier

  • Purpose: Data stored for at least 30 days that is accessed infrequently
  • Latency: Milliseconds (same as Hot)
  • Minimum storage duration: 30 days (early deletion penalty applies)
  • Use cases: Short-term backups, older media content, data awaiting processing

Cold Tier

  • Purpose: Data stored for at least 90 days that is rarely accessed
  • Latency: Milliseconds (same as Hot)
  • Minimum storage duration: 90 days (early deletion penalty applies)
  • Use cases: Disaster recovery data, compliance archives accessed quarterly

Archive Tier

  • Purpose: Data stored for at least 180 days that is almost never accessed
  • Latency: Hours (requires rehydration before access)
  • Minimum storage duration: 180 days (early deletion penalty applies)
  • Use cases: Long-term regulatory archives, raw historical data, legal hold documents

Cost Comparison

Approximate pricing per GB/month (East US, LRS, as of 2024 — check Azure pricing for current rates):

TierStorage Cost (per GB/month)Read Cost (per 10K ops)Write Cost (per 10K ops)Data Retrieval (per GB)
Hot$0.018$0.004$0.05Free
Cool$0.010$0.01$0.10$0.01
Cold$0.0036$0.01$0.18$0.03
Archive$0.0012$5.00$0.10$0.022

Key insight: Storage cost decreases as you move to cooler tiers, but access/retrieval costs increase. The break-even point depends on how often you access the data.

When Each Tier Saves Money

Access PatternBest TierReasoning
Accessed dailyHotLow access costs offset higher storage
Accessed monthlyCool44% storage savings outweigh occasional access costs
Accessed quarterlyCold80% storage savings, acceptable retrieval costs
Accessed yearly or neverArchive93% storage savings, high retrieval cost acceptable

Early Deletion Penalties

If you delete or move a blob to a different tier before the minimum storage duration, you are charged for the remaining days:

TierMinimum DurationPenalty
Cool30 daysCharged for remaining days at Cool rate
Cold90 daysCharged for remaining days at Cold rate
Archive180 daysCharged for remaining days at Archive rate

Example: If you upload a blob to Cool tier and delete it after 10 days, you pay for 30 days of Cool storage (the remaining 20 days are the penalty).

Tip: Factor early deletion penalties into your tier selection. If data might be needed within 30 days, keep it in Hot.


Setting Access Tiers

Via Azure CLI

# Set tier during upload
az storage blob upload \
  --account-name mystorageaccount \
  --container-name data \
  --name logs/2024/january.csv \
  --file ./january.csv \
  --tier Cool

# Change tier on an existing blob
az storage blob set-tier \
  --account-name mystorageaccount \
  --container-name data \
  --name logs/2024/january.csv \
  --tier Archive

# Batch change tier for all blobs with a prefix
az storage blob list \
  --account-name mystorageaccount \
  --container-name data \
  --prefix "logs/2023/" \
  --query "[].name" -o tsv | \
while read blob; do
  az storage blob set-tier \
    --account-name mystorageaccount \
    --container-name data \
    --name "$blob" \
    --tier Archive
done

Via C# SDK

using Azure.Storage.Blobs;
using Azure.Storage.Blobs.Models;

var connectionString = Environment.GetEnvironmentVariable("STORAGE_CONNECTION_STRING");
var blobServiceClient = new BlobServiceClient(connectionString);
var containerClient = blobServiceClient.GetBlobContainerClient("data");

// Set tier on a single blob
var blobClient = containerClient.GetBlobClient("logs/2024/january.csv");
await blobClient.SetAccessTierAsync(AccessTier.Cool);

// Set tier during upload
var uploadOptions = new BlobUploadOptions
{
    AccessTier = AccessTier.Cool
};
await blobClient.UploadAsync(stream, uploadOptions);

// Batch tier change for multiple blobs
await foreach (var blobItem in containerClient.GetBlobsAsync(prefix: "logs/2023/"))
{
    var blob = containerClient.GetBlobClient(blobItem.Name);
    await blob.SetAccessTierAsync(AccessTier.Archive);
}

Lifecycle Management Policies

Automate tier transitions based on age, last access time, or other conditions:

Via Azure Portal

  1. Storage Account → Data managementLifecycle management
  2. Click Add a rule
  3. Define conditions (e.g., "Move to Cool after 30 days")
  4. Save

Via JSON Policy

{
  "rules": [
    {
      "name": "move-logs-to-cool",
      "enabled": true,
      "type": "Lifecycle",
      "definition": {
        "filters": {
          "blobTypes": ["blockBlob"],
          "prefixMatch": ["logs/"]
        },
        "actions": {
          "baseBlob": {
            "tierToCool": {
              "daysAfterModificationGreaterThan": 30
            },
            "tierToCold": {
              "daysAfterModificationGreaterThan": 90
            },
            "tierToArchive": {
              "daysAfterModificationGreaterThan": 180
            },
            "delete": {
              "daysAfterModificationGreaterThan": 730
            }
          }
        }
      }
    }
  ]
}

Apply via CLI

az storage account management-policy create \
  --account-name mystorageaccount \
  --resource-group myRG \
  --policy @lifecycle-policy.json

Last Access Time Tracking

Enable last access time tracking to tier based on actual usage rather than creation date:

# Enable last access time tracking
az storage account blob-service-properties update \
  --account-name mystorageaccount \
  --resource-group myRG \
  --enable-last-access-tracking true

Then use daysAfterLastAccessTimeGreaterThan in your policy:

{
  "actions": {
    "baseBlob": {
      "tierToCool": {
        "daysAfterLastAccessTimeGreaterThan": 30
      }
    }
  }
}

Rehydration from Archive

Archive blobs cannot be read directly. You must rehydrate them to Hot or Cool tier first.

Rehydration Options

MethodDurationCostUse When
StandardUp to 15 hoursLowerNon-urgent access
High PriorityUnder 1 hour (for blobs < 10 GB)HigherUrgent access needed

Rehydrate by Changing Tier

// Standard priority (up to 15 hours)
await blobClient.SetAccessTierAsync(AccessTier.Hot);

// High priority (under 1 hour for small blobs)
await blobClient.SetAccessTierAsync(AccessTier.Hot,
    rehydratePriority: RehydratePriority.High);

Rehydrate by Copying

The recommended approach — creates a new blob in the target tier without modifying the archive blob:

var sourceBlob = containerClient.GetBlobClient("archive/old-report.pdf");
var destBlob = containerClient.GetBlobClient("active/old-report.pdf");

var copyOptions = new BlobCopyFromUriOptions
{
    AccessTier = AccessTier.Hot,
    RehydratePriority = RehydratePriority.High
};

var operation = await destBlob.StartCopyFromUriAsync(sourceBlob.Uri, copyOptions);
await operation.WaitForCompletionAsync();

Checking Rehydration Status

var properties = await blobClient.GetPropertiesAsync();

if (properties.Value.ArchiveStatus != null)
{
    Console.WriteLine($"Rehydration in progress: {properties.Value.ArchiveStatus}");
    // Possible values: "rehydrate-pending-to-hot", "rehydrate-pending-to-cool"
}
else if (properties.Value.AccessTier == "Archive")
{
    Console.WriteLine("Blob is archived, not rehydrating");
}
else
{
    Console.WriteLine($"Blob is accessible in {properties.Value.AccessTier} tier");
}

Real-World Scenarios

Scenario 1: Application Log Archival

Day 0-7:    Hot tier    → Active debugging and monitoring
Day 7-30:   Cool tier   → Occasional investigation
Day 30-90:  Cold tier   → Rare compliance queries
Day 90-365: Archive     → Regulatory retention
Day 365+:   Delete      → Retention period expired

Scenario 2: Media Asset Management

Upload:     Hot tier    → Immediate streaming/editing
After 30d:  Cool tier   → Occasional re-access by users
After 180d: Archive     → Long-term preservation
On demand:  Rehydrate   → User requests old content

Scenario 3: Data Lake Cost Optimization

Raw data:       Hot tier    → Active ETL processing
Processed data: Cool tier   → Periodic re-analysis
Historical:     Cold tier   → Quarterly reporting
Legacy:         Archive     → Compliance retention only

Scenario 4: Backup Strategy

Daily backups:   Hot (7 days) → Quick restore
Weekly backups:  Cool (30 days) → Recent recovery
Monthly backups: Cold (1 year) → Disaster recovery
Yearly backups:  Archive (7 years) → Regulatory compliance

Best Practices

  1. Start with lifecycle policies — Don't rely on manual tier changes. Automate transitions based on data age or last access time.

  2. Enable last access time tracking — Tier based on actual usage patterns rather than assumptions about data age.

  3. Account for early deletion penalties — If data might be needed within the minimum duration, keep it in a higher tier. The penalty can exceed the savings.

  4. Use copy-based rehydration — When rehydrating from Archive, copy to a new blob rather than changing the tier in place. This preserves the archive copy and gives you more control.

  5. Plan for rehydration latency — Archive rehydration takes hours. If you might need data urgently, keep it in Cold instead of Archive.

  6. Set the default account tier — Configure your storage account's default access tier to match your most common workload:

az storage account update \
  --name mystorageaccount \
  --resource-group myRG \
  --access-tier Cool
  1. Monitor tier distribution — Use Azure Monitor to track how much data sits in each tier and whether your lifecycle policies are working as expected.

  2. Consider blob-level tiering — You can set different tiers per blob within the same container. Use this for mixed-access patterns.

  3. Factor in all costs — Compare total cost (storage + access + retrieval + early deletion) not just storage cost per GB.

  4. Test rehydration workflows — Before archiving critical data, verify your rehydration process works and meets your RTO (Recovery Time Objective).


Common Pitfalls

PitfallImpactSolution
Archiving frequently accessed dataHigh retrieval costs exceed savingsAnalyze access patterns before archiving
Ignoring early deletion penaltiesUnexpected charges when data is needed earlyUse Hot/Cool for data with uncertain access patterns
No rehydration planHours of delay when archive data is urgently neededKeep recent data in Cold (not Archive) if urgent access is possible
Lifecycle policy conflictsMultiple rules applying to same blobsUse specific prefix filters, test policies in dev first
Forgetting about snapshotsSnapshots inherit tier but are billed separatelyInclude snapshot management in lifecycle policies

Next Steps


Azure Integration Hub - Intermediate Level