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):
| Tier | Storage Cost (per GB/month) | Read Cost (per 10K ops) | Write Cost (per 10K ops) | Data Retrieval (per GB) |
|---|---|---|---|---|
| Hot | $0.018 | $0.004 | $0.05 | Free |
| 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 Pattern | Best Tier | Reasoning |
|---|---|---|
| Accessed daily | Hot | Low access costs offset higher storage |
| Accessed monthly | Cool | 44% storage savings outweigh occasional access costs |
| Accessed quarterly | Cold | 80% storage savings, acceptable retrieval costs |
| Accessed yearly or never | Archive | 93% 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:
| Tier | Minimum Duration | Penalty |
|---|---|---|
| Cool | 30 days | Charged for remaining days at Cool rate |
| Cold | 90 days | Charged for remaining days at Cold rate |
| Archive | 180 days | Charged 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
- Storage Account → Data management → Lifecycle management
- Click Add a rule
- Define conditions (e.g., "Move to Cool after 30 days")
- 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
| Method | Duration | Cost | Use When |
|---|---|---|---|
| Standard | Up to 15 hours | Lower | Non-urgent access |
| High Priority | Under 1 hour (for blobs < 10 GB) | Higher | Urgent 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
-
Start with lifecycle policies — Don't rely on manual tier changes. Automate transitions based on data age or last access time.
-
Enable last access time tracking — Tier based on actual usage patterns rather than assumptions about data age.
-
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.
-
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.
-
Plan for rehydration latency — Archive rehydration takes hours. If you might need data urgently, keep it in Cold instead of Archive.
-
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
-
Monitor tier distribution — Use Azure Monitor to track how much data sits in each tier and whether your lifecycle policies are working as expected.
-
Consider blob-level tiering — You can set different tiers per blob within the same container. Use this for mixed-access patterns.
-
Factor in all costs — Compare total cost (storage + access + retrieval + early deletion) not just storage cost per GB.
-
Test rehydration workflows — Before archiving critical data, verify your rehydration process works and meets your RTO (Recovery Time Objective).
Common Pitfalls
| Pitfall | Impact | Solution |
|---|---|---|
| Archiving frequently accessed data | High retrieval costs exceed savings | Analyze access patterns before archiving |
| Ignoring early deletion penalties | Unexpected charges when data is needed early | Use Hot/Cool for data with uncertain access patterns |
| No rehydration plan | Hours of delay when archive data is urgently needed | Keep recent data in Cold (not Archive) if urgent access is possible |
| Lifecycle policy conflicts | Multiple rules applying to same blobs | Use specific prefix filters, test policies in dev first |
| Forgetting about snapshots | Snapshots inherit tier but are billed separately | Include snapshot management in lifecycle policies |
Next Steps
- Lifecycle Management Policies — Deep dive into automated tier management
- Blob Storage Monitoring — Track costs and access patterns
Azure Integration Hub - Intermediate Level