Azure Blob tiers and a lifecycle management policy without the early-deletion bill
Cool, cold and archive cost less per gigabyte and each has a minimum stay, 30, 90 and 180 days, charged pro rata when a blob is deleted, overwritten or moved earlier. A lifecycle management policy runs once a day and takes up to a day to start. The tier to upload into, the rules that don't bounce blobs back and forth, how last-access tracking works, and what archive really costs in time.
Data & storageFix a problem7 min read
An Azure Blob lifecycle management policy is the cheapest cost saving in a storage account: a few rules that move ageing blobs to cool, cold or archive and delete them at the end of their life, run for you once a day. It's also where the surprise invoices come from, because every tier below hot has a minimum stay, and a blob that leaves early, by deletion, by overwrite or by a policy that moves it again, is charged for the days it didn't stay. This guide sets out the tiers and their minimums, the policy that respects them, the last-access tracking that makes "unused for 30 days" mean what you think, and the hours (not seconds) that archive takes to give data back.
The four tiers and their minimum stays
| Tier | For | Minimum stay | Online? |
|---|---|---|---|
| Hot | Data in active use | None | Yes |
| Cool | Infrequently used, kept at least a month | 30 days | Yes |
| Cold | Rarely used, kept at least three months | 90 days | Yes |
| Archive | Rarely if ever read, kept at least half a year | 180 days | No: must be rehydrated before it can be read or changed |
The minimum stay is enforced as an early deletion charge, prorated. A blob moved to cool and deleted after 21 days is charged for the 9 days it didn't stay; an archived blob deleted after 120 days is charged for 180. Moving to another tier counts as leaving, and so does rewriting the whole blob (Put Blob, Put Block List, Copy Blob onto it) inside the window. With soft delete on, a blob isn't "deleted" until its retention period ends, so the charge waits too. Archived blobs keep their metadata online, billed at cool rates, so you can still list them and read their tags.
Each colder tier also charges more per operation and per gigabyte read, so a cool tier that's read every day can cost more than hot. The tiers are about access patterns, not about how old a file is.
Upload into the right tier
Set the tier when you upload. A blob written to hot and tiered to cool later pays for the write twice (once per tier) and for its days in hot, and a policy adds a day to take effect and up to a day to run. For a known-cold workload, write cool or cold from the start; for an offline migration of a large estate, Data Box can land data in the tier you want.
Changing tiers afterwards:
- Hot to cool, cool to cold, any online tier to archive:
Set Blob Tier, instant, and the early-deletion clock starts. - Cold or cool back to hot: instant, with the early-deletion charge if the stay was short.
- Archive to an online tier: rehydration. Standard priority can take up to 15 hours for an object under 10 GB; high priority may finish in under an hour for such objects, costs more, and the account as a whole is limited to about 10 GiB an hour of high-priority rehydration, so a bulk restore doesn't scale linearly. You can raise a pending standard request to high. Don't poll
Get Blob Propertiesfor 15 hours; subscribe to theMicrosoft.Storage.BlobTierChangedevent instead. - Copy Blob to a new blob in the target tier avoids the early-deletion charge on the source (which stays where it is), at the cost of storing two blobs.
A lifecycle policy can't rehydrate; archive is a one-way door for the policy.
Write the policy
A policy is JSON with rules; each rule has a filter (blob types, name prefixes, index tags) and actions on the base blob, previous versions and snapshots. This one ages out application logs and respects every minimum:
{
"rules": [
{
"enabled": true,
"name": "age-out-logs",
"type": "Lifecycle",
"definition": {
"filters": { "blobTypes": ["blockBlob"], "prefixMatch": ["logs/"] },
"actions": {
"baseBlob": {
"tierToCool": { "daysAfterModificationGreaterThan": 30 },
"tierToArchive": {
"daysAfterModificationGreaterThan": 120,
"daysAfterLastTierChangeGreaterThan": 90
},
"delete": { "daysAfterModificationGreaterThan": 730 }
}
}
}
}
]
}
Why those numbers: cool at 30 days of no modification; archive at 120, which is 90 days after the move to cool, so the cool minimum is met; delete at two years, long past the archive minimum. daysAfterLastTierChangeGreaterThan also stops a rehydrated blob being re-archived the next day, because rehydration doesn't update the modified or last-access time, and without it the archive rule would pull the blob straight back.
The rest of what Learn says about rules:
- Conditions are days since modification, since creation, since last access (see the next section), or since the last tier change (archive actions only).
- If several actions apply to one blob in one run, the least expensive wins: delete over archive, archive over cool.
- Archive isn't available for append or page blobs, premium block blob accounts, blobs with an encryption scope, or accounts on ZRS, GZRS or RA-GZRS redundancy. Delete can't touch an immutable container.
- A new or changed policy takes up to 24 hours to take effect; it then runs once a day, and a large account may need more than one run to get through everything. Resource logs show what it did.
- If capacity doesn't fall after deletions, soft delete or versioning is keeping the data, as it should.
Test a rule on a prefix first, and keep a delete rule separate from the tiering rules so it can be disabled on its own.
Last-access tracking and auto-tiering
"Not accessed for 30 days" is a different condition from "not modified for 30 days", and it needs last access time tracking turned on for the account. Once it is, reads and writes update a LastAccessTime property; reading properties, metadata or tags doesn't count. For blobs that existed before tracking started, the clock begins when tracking was enabled.
The companion setting is enableAutoTierToHotFromCool: a blob the policy moved to cool goes back to hot when it's read. It applies only with the last-access condition, only to blobs this rule moved down, and at most once in 30 days per blob, a safeguard against paying the cool minimum repeatedly. If a blob needs tiering up more than once a month, leave it in hot. Two quirks worth knowing: the property can't be enabled for blobs already in cool, and disabling the rule doesn't stop the auto-tiering, because that happens on access; only turning off tracking does.
Find out before you move
Run blob inventory reports and enable last-access tracking for a month before you write the policy, then look at what's actually read. Learn's rule of thumb is cool for data untouched for more than 30 days and archive for more than 180, but your own numbers are the ones that count. For many accounts, Azure Storage Actions runs the same kind of rules across all of them with parameters and prefix exclusions, so the curated paths are never touched.
Sources
- Access tiers for blob data, Microsoft Learn (the tiers, the minimum stays and the prorated early-deletion charge, soft delete, archive metadata)
- Best practices for using blob access tiers, Microsoft Learn (upload into the right tier, inventory and last-access analysis)
- Azure Blob Storage lifecycle management overview, Microsoft Learn
- Lifecycle management policy structure, Microsoft Learn (actions, conditions, the least-expensive rule, access time tracking, the restrictions)
- Lifecycle management policy FAQ, Microsoft Learn (the 24 hours, multiple runs, soft delete and versioning, auto-tiering after a rule is disabled)
- Lifecycle management policies that transition blobs between tiers, Microsoft Learn (the auto-tier-to-hot safeguard)
- Blob rehydration from the archive tier, Microsoft Learn (priorities, the 10 GiB per hour limit, the event)
- Archive a blob, Microsoft Learn (the policy runs once per day)
- Azure Blob Storage cost optimization services and capabilities, Microsoft Learn (Storage Actions)
Did this fix it?
Comments
No comments yet. Share what worked for you.
Sign in to comment. Comments show under a display name you choose, never your email.