Theoretical Foundation: Configure Blob Lifecycle Management
1. Initial Intuitionβ
Imagine you manage a physical document archive in a company. There are clear rules: current month documents stay on your work desk (immediate access); documents older than 3 months go to the dead file in the hallway (occasional access); documents older than 1 year go to external storage (rarely accessed); and documents older than 7 years are shredded (legal obligation fulfilled).
You don't do this process manually every day. You define the rules once and the process happens automatically.
Blob Lifecycle Management is exactly this system of automated rules applied to Azure Blob Storage. You define policies that tell Azure: "after X days, move this blob to a cheaper tier; after Y days, delete it". Azure executes these rules automatically, without human intervention.
The practical result is cost reduction without sacrificing availability, because older and less accessed data automatically migrates to cheaper tiers.
2. Contextβ
2.1 Why Lifecycle Management existsβ
Without automation, storage cost grows indefinitely because:
- Data is never moved between tiers manually in a consistent way
- Old data continues to pay Hot tier prices
- Data that should be deleted remains
Lifecycle Management closes this cycle automatically. It's the tool that transforms storage tiers theory into scalable operational practice.
2.2 Relationship with Storage Tiersβ
Lifecycle Management and Storage Tiers are distinct but deeply connected concepts:
- Storage Tiers (Hot, Cool, Cold, Archive) are the "shelves" with different prices
- Lifecycle Management is the "rule system" that moves blobs between these shelves automatically
You can have tiers without lifecycle management (changing tiers manually), but Lifecycle Management only makes sense when there are tiers to transition between.
2.3 Application scopeβ
Lifecycle Management is configured at the Storage Account level and applies to:
- Block Blobs (full support for all tiers)
- Append Blobs (deletion only, no tier changes)
- Page Blobs (not supported)
- Blobs in Standard GPv2 and Premium Block Blob accounts (deletion only in Premium)
3. Concept Constructionβ
3.1 The structure of a Lifecycle Management policyβ
A lifecycle policy is a JSON document that contains a collection of rules. Each rule is independent and composed of two elements:
Filters: Determine which blobs the rule applies to. Actions: Determine what to do with blobs that pass the filter.
3.2 Available filtersβ
Filters determine the scope of each rule:
blobTypes: Defines the target blob type.
"blobTypes": ["blockBlob"]
"blobTypes": ["appendBlob"]
"blobTypes": ["blockBlob", "appendBlob"]
prefixMatch: List of blob name prefixes. The rule only applies to blobs whose name starts with one of the listed prefixes.
"prefixMatch": [
"backups/2024/",
"logs/app/",
"data/raw/"
]
blobIndexMatch: Filters by Blob Index Tags, key-value pairs associated with the blob. Allows semantic segmentation independent of name.
"blobIndexMatch": [
{
"name": "department",
"op": "==",
"value": "finance"
},
{
"name": "status",
"op": "==",
"value": "processed"
}
]
When to use blobIndexMatch vs prefixMatch: Use
prefixMatchwhen organization is structural (by virtual "folder"). UseblobIndexMatchwhen organization is semantic (by data property, independent of name). Both can be combined in the same rule (AND behavior).
3.3 Available actionsβ
Actions define what happens and when. The when field defines the temporal condition:
Actions on the base blob (baseBlob):
| Action | Description | Conditional when |
|---|---|---|
tierToCool | Move to Cool tier | daysAfterModificationGreaterThan or daysAfterLastAccessTimeGreaterThan or daysAfterCreationGreaterThan |
tierToCold | Move to Cold tier | Same as tierToCool |
tierToArchive | Move to Archive tier | Same as tierToCool |
delete | Delete the blob | Same as tierToCool |
enableAutoTierToHotFromCool | Automatically move from Cool to Hot when accessed | No day condition |
Actions on snapshots (snapshot):
| Action | Conditional |
|---|---|
tierToCool | daysAfterCreationGreaterThan |
tierToCold | daysAfterCreationGreaterThan |
tierToArchive | daysAfterCreationGreaterThan |
delete | daysAfterCreationGreaterThan |
Actions on versions (version):
| Action | Conditional |
|---|---|
tierToCool | daysAfterCreationGreaterThan |
tierToCold | daysAfterCreationGreaterThan |
tierToArchive | daysAfterCreationGreaterThan |
delete | daysAfterCreationGreaterThan |
Important point: Not including actions for
snapshotandversionin the lifecycle policy is a common mistake that results in old snapshots and versions accumulating cost indefinitely.
3.4 Temporal conditionalsβ
Conditionals define when the action is applied:
daysAfterModificationGreaterThan: Counts days since the last modification of the blob. This is the most common pattern.
daysAfterCreationGreaterThan: Counts days since the creation of the blob. Useful for data that is never modified after upload (logs, backups).
daysAfterLastAccessTimeGreaterThan: Counts days since the last access (read or write). Requires Last Access Time Tracking to be enabled on the account. Ideal for data whose access pattern varies.
daysAfterLastTierChangeGreaterThan:
Counts days since the last tier change of the blob. Available only for baseBlob actions and only for tierToArchive and delete. Useful to ensure blobs stay in Cool for a minimum time before going to Archive.
3.5 enableAutoTierToHotFromCoolβ
This special action is different from others: instead of being executed periodically, it instructs Azure to automatically move a blob from Cool to Hot when it is accessed.
This creates a dynamic tiering system: blobs stay in Cool by default, but when accessed they automatically return to Hot, where access cost is lower for frequently read data.
"enableAutoTierToHotFromCool": {}
Doesn't require a day parameter as it's triggered by access, not by time.
4. Structural Overviewβ
5. Practical Functioningβ
5.1 Execution frequency and timingβ
The Lifecycle Management Engine executes once per day. After creating or modifying a policy, it can take up to 48 hours for the first execution to occur. After this period, execution is daily.
This has practical implications:
- It's not a real-time system
- Blobs are not moved immediately when the condition is met
- There can be a window of up to 24 hours between the condition being met and the action being executed
5.2 Action execution orderβ
When multiple actions apply to the same blob (e.g., tierToCool and delete both with conditions met), Azure executes the most economical action first:
The order of precedence (from highest to lowest priority) is: delete > tierToArchive > tierToCold > tierToCool.
In practice: if a blob meets the condition for tierToCool (30 days) and delete (365 days) simultaneously, the blob is deleted, not moved to Cool.
5.3 Behavior with blob versioningβ
When Blob Versioning is enabled, the baseBlob section of the lifecycle policy affects only the current version of the blob. Previous versions are controlled by the version section.
If you don't include actions for version, old versions accumulate in Hot indefinitely, generating growing costs.
5.4 Complete policy example for real scenarioβ
Scenario: Storage Account for an e-commerce application with logs, product images, and backups.
{
"rules": [
{
"name": "log-retention",
"enabled": true,
"type": "Lifecycle",
"definition": {
"filters": {
"blobTypes": ["appendBlob"],
"prefixMatch": ["logs/"]
},
"actions": {
"baseBlob": {
"delete": {
"daysAfterCreationGreaterThan": 90
}
}
}
}
},
{
"name": "product-images",
"enabled": true,
"type": "Lifecycle",
"definition": {
"filters": {
"blobTypes": ["blockBlob"],
"prefixMatch": ["images/products/"]
},
"actions": {
"baseBlob": {
"enableAutoTierToHotFromCool": {},
"tierToCool": {
"daysAfterLastAccessTimeGreaterThan": 30
},
"tierToArchive": {
"daysAfterLastAccessTimeGreaterThan": 365
}
},
"snapshot": {
"delete": {
"daysAfterCreationGreaterThan": 30
}
}
}
}
},
{
"name": "backup-tiering",
"enabled": true,
"type": "Lifecycle",
"definition": {
"filters": {
"blobTypes": ["blockBlob"],
"prefixMatch": ["backups/"]
},
"actions": {
"baseBlob": {
"tierToCool": {
"daysAfterModificationGreaterThan": 30
},
"tierToCold": {
"daysAfterModificationGreaterThan": 90
},
"tierToArchive": {
"daysAfterModificationGreaterThan": 180
},
"delete": {
"daysAfterModificationGreaterThan": 2555
}
}
}
}
}
]
}
6. Implementation Methodsβ
6.1 Azure Portalβ
When to use: Visual creation of simple rules, checking existing configuration, test environments.
Navigate to: Storage Account > Data Management > Lifecycle Management > Add rule
The portal offers two approaches:
- Visual: Form interface where you select filters and actions via dropdowns and numeric fields.
- Code View: Direct JSON editor, useful for more complex rules or to paste ready configurations.
Limitation: The portal doesn't support blobIndexMatch in the complete visual interface; use Code View for this functionality.
6.2 Azure CLIβ
Create policy from JSON file:
az storage account management-policy create \
--account-name myaccount \
--resource-group myRG \
--policy @lifecycle-policy.json
View current policy:
az storage account management-policy show \
--account-name myaccount \
--resource-group myRG
Update existing policy (completely replaces):
az storage account management-policy update \
--account-name myaccount \
--resource-group myRG \
--set 'policy.rules[0].definition.actions.baseBlob.delete.daysAfterModificationGreaterThan=365'
Delete policy:
az storage account management-policy delete \
--account-name myaccount \
--resource-group myRG
6.3 Azure PowerShellβ
# Create rules individually and combine
$rule1 = New-AzStorageAccountManagementPolicyRule `
-Name "log-retention" `
-Enabled `
-Filter (New-AzStorageAccountManagementPolicyFilter `
-BlobType appendBlob `
-PrefixMatch "logs/") `
-Action (New-AzStorageAccountManagementPolicyAction `
-BaseBlob (New-AzStorageAccountManagementPolicyBaseBlob `
-DeleteDaysAfterCreationGreaterThan 90))
$rule2 = New-AzStorageAccountManagementPolicyRule `
-Name "backup-tiering" `
-Enabled `
-Filter (New-AzStorageAccountManagementPolicyFilter `
-BlobType blockBlob `
-PrefixMatch "backups/") `
-Action (New-AzStorageAccountManagementPolicyAction `
-BaseBlob (New-AzStorageAccountManagementPolicyBaseBlob `
-TierToCoolDaysAfterModificationGreaterThan 30 `
-TierToArchiveDaysAfterModificationGreaterThan 180 `
-DeleteDaysAfterModificationGreaterThan 2555))
Set-AzStorageAccountManagementPolicy `
-ResourceGroupName "myRG" `
-StorageAccountName "myaccount" `
-Rule $rule1, $rule2
6.4 Bicepβ
resource managementPolicy 'Microsoft.Storage/storageAccounts/managementPolicies@2023-01-01' = {
name: '${storageAccount.name}/default'
properties: {
policy: {
rules: [
{
name: 'log-retention'
enabled: true
type: 'Lifecycle'
definition: {
filters: {
blobTypes: ['appendBlob']
prefixMatch: ['logs/']
}
actions: {
baseBlob: {
delete: {
daysAfterCreationGreaterThan: 90
}
}
}
}
}
{
name: 'backup-tiering'
enabled: true
type: 'Lifecycle'
definition: {
filters: {
blobTypes: ['blockBlob']
prefixMatch: ['backups/']
}
actions: {
baseBlob: {
tierToCool: {
daysAfterModificationGreaterThan: 30
}
tierToArchive: {
daysAfterModificationGreaterThan: 180
}
delete: {
daysAfterModificationGreaterThan: 2555
}
}
snapshot: {
# Storage Account Lifecycle Management - Complete Technical Guide
This guide provides comprehensive coverage of Azure Storage Account Lifecycle Management, from basic concepts to advanced configurations and operational practices.
---
## 1. Introduction and Basic Concepts
**Azure Storage Lifecycle Management** is an automated system that defines rules for moving blobs between access tiers (Hot, Cool, Cold, Archive) or deleting them based on time-based conditions.
### 1.1 How it works
- The engine runs **once daily** (approximately 24-hour intervals)
- Rules are evaluated in the order they appear in the policy JSON
- A blob can be affected by multiple rules, but **action precedence** determines what happens: `delete` > `tierToArchive` > `tierToCold` > `tierToCool`
### 1.2 Practical use cases
- **Automatic archiving** of logs after 90 days without access
- **Deletion** of temporary files after 30 days of creation
- **Moving inactive files** from Hot to Cool after 30 days without modification
- **Legal compliance:** retain documents for N years, then automatically delete
---
## 2. Policy Structure
### 2.1 Complete hierarchy
```json
{
"rules": [
{
"name": "rule-name",
"enabled": true,
"type": "Lifecycle",
"definition": {
"filters": {
"blobTypes": ["blockBlob"],
"prefixMatch": ["container1/folder1/", "container2/"],
"blobIndexMatch": [
{"name": "department", "op": "==", "value": "finance"},
{"name": "retention_years", "op": ">=", "value": "7"}
]
},
"actions": {
"baseBlob": {
"tierToCool": {
"daysAfterModificationGreaterThan": 30
},
"tierToCold": {
"daysAfterModificationGreaterThan": 90
},
"tierToArchive": {
"daysAfterModificationGreaterThan": 180
},
"delete": {
"daysAfterModificationGreaterThan": 365
}
},
"snapshot": {
"tierToCool": {
"daysAfterCreationGreaterThan": 7
},
"delete": {
"daysAfterCreationGreaterThan": 30
}
},
"version": {
"tierToCool": {
"daysAfterCreationGreaterThan": 7
},
"delete": {
"daysAfterCreationGreaterThan": 90
}
}
}
}
}
]
}
2.2 Critical sectionsβ
| Section | Purpose | Required |
|---|---|---|
baseBlob | Actions on the blob itself | Yes |
snapshot | Actions on blob snapshots | Only if snapshots exist |
version | Actions on blob versions | Only if Blob Versioning is enabled |
Important: If your account has Blob Versioning enabled and you omit the
versionsection, previous versions will accumulate indefinitely, generating unexpected costs.
3. Time-Based Conditionalsβ
3.1 Available optionsβ
| Conditional | Reference Event | Typical Use Case |
|---|---|---|
daysAfterCreationGreaterThan | Blob creation date | Logs, backups, immutable data |
daysAfterModificationGreaterThan | Last modification date | Documents, images, dynamic files |
daysAfterLastAccessTimeGreaterThan | Last read date | Mixed data with irregular access |
daysAfterLastTierChangeGreaterThan | Last tier change | Avoid premature deletion after tier change |
3.2 Example combinationsβ
{
"name": "progressive-archive",
"definition": {
"actions": {
"baseBlob": {
"tierToCool": {
"daysAfterModificationGreaterThan": 30
},
"tierToArchive": {
"daysAfterModificationGreaterThan": 90,
"daysAfterLastTierChangeGreaterThan": 30
},
"delete": {
"daysAfterCreationGreaterThan": 2555
}
}
}
}
}
This rule:
- Moves to Cool after 30 days without modification
- Moves to Archive after 90 days without modification AND 30 days since last tier change
- Deletes after 7 years (2555 days) from creation, regardless of modifications
4. Filtersβ
4.1 prefixMatchβ
Filters blobs by name/path:
"prefixMatch": ["logs/app1/", "backups/", "temp-"]
- A blob named
logs/app1/2025/01/access.logmatches the prefixlogs/app1/ - A blob named
temp-file-123.txtmatches the prefixtemp- - Prefixes are literal (not regex)
4.2 blobIndexMatchβ
Filters blobs by Index Tags (metadata):
"blobIndexMatch": [
{"name": "department", "op": "==", "value": "finance"},
{"name": "retention_period", "op": ">=", "value": "5"}
]
Available operators:
==(equals)!=(not equals)>=and<=(numeric comparison)
For this to work, blobs must have been tagged:
az storage blob tag set \
--account-name mystorageaccount \
--container-name mycontainer \
--name myblob.txt \
--tags department=finance retention_period=7
4.3 Combining filtersβ
When multiple filters are present, they work with AND logic:
"filters": {
"blobTypes": ["blockBlob"],
"prefixMatch": ["documents/"],
"blobIndexMatch": [
{"name": "confidential", "op": "==", "value": "true"}
]
}
This matches block blobs that start with documents/ and have the tag confidential=true.
5. Configuration via Azure CLIβ
5.1 Basic creationβ
# Create policy from JSON file
az storage account management-policy create \
--account-name mystorageaccount \
--resource-group myresourcegroup \
--policy @lifecycle-policy.json
5.2 Enable Last Access Time Trackingβ
Required for daysAfterLastAccessTimeGreaterThan to work:
az storage account blob-service-properties update \
--account-name mystorageaccount \
--resource-group myresourcegroup \
--enable-last-access-tracking true
Important: This generates an additional transaction for each blob read. Evaluate the cost/benefit based on your access pattern.
5.3 View current policyβ
az storage account management-policy show \
--account-name mystorageaccount \
--resource-group myresourcegroup \
--output json
5.4 Delete policyβ
az storage account management-policy delete \
--account-name mystorageaccount \
--resource-group myresourcegroup
6. Practical Examplesβ
6.1 Log archiving policyβ
{
"rules": [
{
"name": "archive-application-logs",
"enabled": true,
"type": "Lifecycle",
"definition": {
"filters": {
"blobTypes": ["blockBlob"],
"prefixMatch": ["logs/application/"]
},
"actions": {
"baseBlob": {
"tierToCool": {
"daysAfterCreationGreaterThan": 30
},
"tierToArchive": {
"daysAfterCreationGreaterThan": 90
},
"delete": {
"daysAfterCreationGreaterThan": 2555
}
}
}
}
}
]
}
6.2 Policy based on access patternβ
{
"rules": [
{
"name": "user-files-by-access",
"enabled": true,
"type": "Lifecycle",
"definition": {
"filters": {
"blobTypes": ["blockBlob"],
"prefixMatch": ["userdata/"]
},
"actions": {
"baseBlob": {
"tierToCool": {
"daysAfterLastAccessTimeGreaterThan": 30
},
"tierToArchive": {
"daysAfterLastAccessTimeGreaterThan": 90
}
}
}
}
}
]
}
6.3 Complete policy with snapshots and versionsβ
{
"rules": [
{
"name": "complete-backup-lifecycle",
"enabled": true,
"type": "Lifecycle",
"definition": {
"filters": {
"blobTypes": ["blockBlob"],
"prefixMatch": ["backups/"]
},
"actions": {
"baseBlob": {
"tierToCool": {
"daysAfterCreationGreaterThan": 30
},
"delete": {
"daysAfterCreationGreaterThan": 365
}
},
"snapshot": {
"tierToCool": {
"daysAfterCreationGreaterThan": 7
},
"delete": {
"daysAfterCreationGreaterThan": 30
}
},
"version": {
"delete": {
"daysAfterCreationGreaterThan": 90
}
}
}
}
}
]
}
7. Control and Securityβ
7.1 Required permissionsβ
Lifecycle Management Policy is a control plane configuration:
| Operation | Minimum Role |
|---|---|
| Create/edit policy | Storage Account Contributor |
| View policy | Storage Account Reader |
| Delete policy | Storage Account Contributor |
Important distinction:
Storage Blob Data Contributordoes not have permission to create or edit lifecycle policies. A control plane (account management) role is required.
7.2 Impact of policies on critical dataβ
Lifecycle policies with delete actions are irreversible if Soft Delete is not enabled. If an incorrect rule deletes blobs, without Soft Delete there's no recovery.
Security practices:
- Test in non-production account before applying policies with
deletein production. - Enable Soft Delete with sufficient retention period to detect incorrect deletions by lifecycle policy.
- Use
enabled: falsewhen initially creating a rule to validate configuration before activating. - Review policy with
az storage account management-policy showbefore applying in production.
7.3 Action traceabilityβ
Configure diagnostics to track which blobs were affected by lifecycle policy:
az monitor diagnostic-settings create \
--name "lifecycle-audit" \
--resource <storage-account-id> \
--logs '[
{"category": "StorageDelete", "enabled": true},
{"category": "StorageWrite", "enabled": true}
]' \
--workspace <log-analytics-workspace-id>
Lifecycle policy deletion logs appear with UserAgent containing StorageLifecycleManagement.
8. Decision Makingβ
8.1 Choosing temporal conditionalβ
| Situation | Recommended conditional | Reason |
|---|---|---|
| Logs, backups (write-once) | daysAfterCreationGreaterThan | Never modified after upload; creation is the relevant event |
| Images, editable documents | daysAfterModificationGreaterThan | Modification indicates active use |
| Assets with irregular access | daysAfterLastAccessTimeGreaterThan | Actual access is the correct indicator |
| Blobs recently moved between tiers | daysAfterLastTierChangeGreaterThan | Avoids premature deletion after tier change |
8.2 Rule structure: granular vs comprehensiveβ
| Approach | Advantage | Disadvantage |
|---|---|---|
| One rule per data type | Precise control per category | Many rules, more complexity |
| Few comprehensive rules with prefixes | Simple to maintain | Less flexibility per data type |
| Rules by Blob Index Tags | Fully semantic, independent of name | Requires blobs to have defined tags |
8.3 daysAfterLastAccessTimeGreaterThan: when to useβ
| Situation | Use? | Reason |
|---|---|---|
| Account with many reads (e.g., CDN origin) | Evaluate cost | Transaction overhead per read |
| Account with few reads but varied data | Yes | Precise tiering with low overhead |
| Write-once blobs without expected reads | No | daysAfterCreationGreaterThan is simpler |
| Mix of hot and cold data in same container | Yes | Avoids moving data that's still accessed |
9. Best Practicesβ
- Always include actions for
snapshotandversionin rules affecting blobs with versioning enabled. Forgetting these sections is the main source of unexpected costs. - Use
enabled: falsewhen creating new rules, validate the JSON structure, and only activate after review. - Separate rules by purpose: One rule for logs, another for backups, another for assets. This facilitates maintenance and debugging.
- Don't overlap prefixes between conflicting rules. If two rules have overlapping prefixes with conflicting actions, both apply to the same blob and precedence order (
delete>archive>cold>cool) decides the result. - Use
blobIndexMatchfor data with different retention requirements that coexist in the same "folder". Tags allow segmentation without reorganizing name structure. - Configure
enableAutoTierToHotFromCoolfor data with irregular access patterns: they stay in Cool by default and automatically return to Hot when accessed. - Enable Last Access Time Tracking before creating rules with
daysAfterLastAccessTimeGreaterThan. Without this, thelastAccessTimefield isn't populated and the rule never triggers. - Document each rule with comments in version control system (IaC). Lifecycle policies are hard to understand months later without context.
- Test projected financial impact using Azure Pricing Calculator with estimated data distribution between tiers.
10. Common Errorsβ
| Error | Why it happens | How to avoid |
|---|---|---|
| Rule doesn't execute after creation | Up to 48h delay on first execution | Wait for complete cycle before diagnosing |
| Snapshots and versions accumulate cost | Rule without snapshot and version sections | Always include all three sections in rules |
daysAfterLastAccessTimeGreaterThan doesn't work | Last Access Time Tracking not enabled | Enable via az storage account blob-service-properties update --enable-last-access-tracking true |
| Rule deletes blobs instead of moving to tier | delete and tier with same condition; delete has precedence | Use different day values: tier first, delete later |
| Policy doesn't apply to newly created blobs | Up to 24h delay for new blobs to enter cycle | Expected behavior; not a bug |
| Incorrect prefix results in uncovered blobs | Prefix without trailing slash covers blobs with similar names | Test prefixes by listing blobs with az storage blob list --prefix |
tierToArchive action fails silently | Blob in Cool tier for less than 30 days (early deletion penalty) | Use daysAfterLastTierChangeGreaterThan to ensure minimum time in Cool before archiving |
| Lifecycle policy accidentally deleted | Single operation that removes entire policy | Version policy in Git repository; use IaC |
11. Operation and Maintenanceβ
11.1 Checking policy executionβ
Diagnostic logs record lifecycle policy operations. To query in Log Analytics:
StorageBlobLogs
| where UserAgentHeader contains "StorageLifecycleManagement"
| where OperationName in ("DeleteBlob", "SetBlobTier")
| summarize count() by OperationName, bin(TimeGenerated, 1d)
| order by TimeGenerated desc
This shows how many blobs were moved or deleted by policy in recent days.
11.2 Monitoring cost per tierβ
az monitor metrics list \
--resource <storage-account-id> \
--metric BlobCapacity \
--dimension Tier \
--interval P1D \
--start-time 2025-01-01T00:00:00Z \
--end-time 2025-01-15T00:00:00Z
Use this metric to validate that tier distribution is as expected and that policy is working correctly.
11.3 Important limitsβ
| Aspect | Limit |
|---|---|
| Maximum rules per policy | 100 |
| Maximum prefixes per rule | 10 |
| Maximum blobIndexMatch per rule | 10 conditions |
| Execution frequency | 1x per day |
| Delay after policy creation | Up to 48 hours |
| Delay for new blobs | Up to 24 hours after upload |
| Supported blob types | Block Blob (complete), Append Blob (delete only) |
| Page Blobs | Not supported |
| Premium accounts | Delete only (no tier changes) |
12. Integration and Automationβ
12.1 Integration with Azure Policy (compliance)β
To ensure every Storage Account has lifecycle management configured:
# Policy built-in: audit storage accounts without lifecycle management
az policy assignment create \
--name "require-lifecycle-policy" \
--policy "26ee67a2-f81a-4ba8-b9ce-8550bd5ee1a7" \
--scope "/subscriptions/<sub-id>"
Also create a custom policy with DeployIfNotExists effect to automatically apply a default policy to new accounts.
12.2 Managing policies via Git repositoryβ
Store lifecycle management JSON in repository and apply via pipeline:
# GitHub Actions: apply lifecycle policy
- name: Apply Lifecycle Policy
uses: azure/CLI@v1
with:
inlineScript: |
az storage account management-policy create \
--account-name ${{ env.STORAGE_ACCOUNT }} \
--resource-group ${{ env.RESOURCE_GROUP }} \
--policy @infrastructure/lifecycle-policies/production.json
12.3 Combining Lifecycle Management with Event Gridβ
To react to tier change events:
az eventgrid event-subscription create \
--name tier-change-monitor \
--source-resource-id <storage-account-id> \
--endpoint <function-url> \
--included-event-types Microsoft.Storage.BlobTierChanged
An Azure Function can then record business metrics, notify teams, or trigger downstream processes when specific blobs change tiers.
13. Final Summaryβ
Essential concepts:
- Lifecycle Management is a system of automatic rules that moves blobs between tiers or deletes them based on time conditions.
- A policy contains rules, each rule has filters (which blobs) and actions (what to do and when).
- The engine executes once daily, with up to 48h delay after policy creation.
Critical differences:
- prefixMatch vs blobIndexMatch: Prefix filters by name (structural). Index match filters by tags (semantic). Can be combined (AND).
- daysAfterModificationGreaterThan vs daysAfterCreationGreaterThan vs daysAfterLastAccessTimeGreaterThan: Each uses a different event as reference. Choose based on actual data lifecycle.
- baseBlob vs snapshot vs version: These are independent sections in actions. Omitting
snapshotorversioncauses these data to accumulate cost indefinitely. - delete has precedence over tierToArchive, which has precedence over tierToCold, which has precedence over tierToCool. If multiple actions apply to the same blob, the highest priority wins.
- Premium accounts: Support only
deletein lifecycle policies. Tier changes are not supported.
What needs to be remembered:
- Maximum of 100 rules per policy and 10 prefixes per rule.
daysAfterLastAccessTimeGreaterThanrequires Last Access Time Tracking enabled separately.- Lifecycle policies only affect Block Blobs and Append Blobs (delete only). Page Blobs are not supported.
- Use
enabled: falseto create inactive rules and activate only after validation. - Always include
snapshotandversionsections in rules when Blob Versioning is enabled. - Soft Delete must be enabled as protection against incorrect deletions by lifecycle policies.
- There's no way to "undo" a deletion caused by lifecycle policy without active Soft Delete.