Azure Storage
Select and configure Azure storage with optimal redundancy, performance tiering, and access controls.
Balance cost, durability, latency, and compliance requirements.
Use This Skill When
- The user needs file, object, or queue storage in Azure
- The user needs lifecycle, replication, or retention policy design
- The user needs secure access model for storage workloads
- The user wants to optimize storage costs while maintaining SLA
Context: Storage Maturity
Immature: Hot tier only, public access, no lifecycle, account key auth
Developing: Correct tiering, RBAC, some lifecycle rules
Managed: LRS for dev, GRS for prod, managed identity auth, lifecycle to cool/archive → Target
Optimized: Geo-redundant reads, tiered access based on traffic, real-time cost optimization
Required Inputs
- Data type: Documents, logs, video, database backups, transactional
- Access pattern: Frequent (hot), occasional (cool), rare (archive), cold
- Size & growth: 10GB initial, 10% monthly growth? Or 1TB spike?
- Latency requirement: <100ms or batch-oriented?
- Durability: RPO/RTO targets? Geographic redundancy needed?
- Access model: Public, private, user-scoped, application-only?
- Compliance: Data residency, encryption, retention, audit requirements?
- Budget: Cost-driven or performance-driven?
Decision Tree
What type of data needs storage?
├─ Unstructured files (docs, images, video) → Blob Storage
├─ Shared file system (SMB/NFS for apps) → Azure Files
├─ Message queue → Queue Storage
├─ NoSQL key-value → Table Storage
├─ Big data analytics → Data Lake Storage
└─ Structured relational → SQL Database (not storage)
How frequently is this data accessed?
├─ Daily (hot, <1 day SLA) → Hot tier ($0.012/GB/month)
├─ Weekly-monthly (cool, <30 day SLA) → Cool tier ($0.001/GB/month)
├─ Rarely, compliance hold (archive, <90 day SLA) → Archive tier ($0.0004/GB/month)
└─ Cold (7+ year retention) → Cold tier ($0.00099/GB/month)
Do you need geographic failover?
├─ Single region (dev/test) → LRS (locally redundant, cheapest, 11x durability)
├─ Single region + replication → ZRS (zone redundant, same-region HA)
├─ Multi-region failover → GRS (geo-redundant, read from secondary)
└─ Multi-region read (active-active) → RA-GRS (read-access geo-redundant)
How should apps access storage?
├─ Internal/private → Private endpoints, firewall rules
├─ Managed identity → System/user-assigned identity with role
├─ Public but controlled → SAS tokens (time-bound, scoped)
└─ Public read-only → Blob public access (for content CDN)
Workflow
Phase 1: Choose Storage Type & Account
Create storage account:
az storage account create \
--resource-group $RG \
--name "st${app}${env}" \
--location eastus \
--kind StorageV2 \
--sku Standard_GRS \
--access-tier Hot \
--https-only \
--default-action Deny
Configure networking (private by default):
# Block all public access
az storage account update \
--resource-group $RG \
--name "st${app}${env}" \
--public-network-access-enabled false
# Or allow only specific IPs/VNets
az storage account network-rule add \
--resource-group $RG \
--account-name "st${app}${env}" \
--vnet-name $VNET \
--subnet-name $SUBNET
Enable encryption (at-rest, in-transit):
# HTTPS only (enforced above)
# At-rest: Default Microsoft-managed keys OR customer-managed key (CMK)
# Use CMK from Key Vault for sensitive data
az storage account update \
--resource-group $RG \
--name "st${app}${env}" \
--encryption-key-name "storage-cmk" \
--encryption-key-vault $KV_ID
Phase 2: Create Containers/Shares & Set Tiering
For Blob Storage:
# Create container
az storage container create \
--account-name "st${app}${env}" \
--name "documents" \
--public-access off
# Or create via Python/C#
# container_client = blob_client.create_container(name="documents")
Set access tier (per blob or policy-driven):
# Set individual blob to cool tier
az storage blob update \
--account-name "st${app}${env}" \
--container-name "documents" \
--name "old-file.pdf" \
--access-tier Cool
For Azure Files:
# Create file share
az storage share create \
--account-name "st${app}${env}" \
--name "shared-files"
# Create subdirectories
az storage directory create \
--account-name "st${app}${env}" \
--share-name "shared-files" \
--name "projects/2024"
Phase 3: Configure Access Controls
Using managed identity (preferred):
# App Service or AKS pod runs with managed identity
# Assign role to identity
PRINCIPAL_ID=$(az identity show --resource-group $RG --name $IDENTITY --query principalId -o tsv)
az role assignment create \
--role "Storage Blob Data Contributor" \
--assignee-object-id $PRINCIPAL_ID \
--scope "/subscriptions/$SUBID/resourceGroups/$RG/providers/Microsoft.Storage/storageAccounts/st${app}${env}"
# In code: DefaultAzureCredential() fetches token automatically
Using SAS tokens (time-bound, scoped):
# Generate SAS token (expires in 1 hour)
EXPIRY=$(date -u -d "+1 hour" +%Y-%m-%dT%H:%M:%SZ)
az storage blob generate-sas \
--account-name "st${app}${env}" \
--container-name "documents" \
--name "file.pdf" \
--permissions r \
--expiry $EXPIRY
# Give user time-limited URL: https://storage.../file.pdf?sv=...&sig=...
Using account key (not recommended for production):
# Get account key
KEY=$(az storage account keys list --resource-group $RG --account-name "st${app}${env}" --query "[0].value" -o tsv)
# Connection string for legacy code
CS="DefaultEndpointsProtocol=https;AccountName=st${app}${env};AccountKey=$KEY;EndpointSuffix=core.windows.net"
# Store in Key Vault
az keyvault secret set --vault-name $KV --name "storage-connection-string" --value "$CS"
Phase 4: Lifecycle Management
Create tiering policy:
{
"rules": [
{
"name": "auto-cool",
"enabled": true,
"type": "Lifecycle",
"definition": {
"filters": {
"blobTypes": ["blockBlob"],
"prefixMatch": ["logs/"]
},
"actions": {
"baseBlob": {
"tierToCool": { "daysAfterModificationGreaterThan": 30 },
"tierToArchive": { "daysAfterModificationGreaterThan": 90 },
"delete": { "daysAfterModificationGreaterThan": 365 }
}
}
}
}
]
}
# Apply policy
az storage account management-policy create \
--account-name "st${app}${env}" \
--resource-group $RG \
--policy @lifecycle.json
Cost impact:
Hot tier: $0.012/GB/month
Cool tier: $0.001/GB/month (83% savings)
Archive: $0.0004/GB/month (97% savings)
But: Archive = 4-hour retrieval, deletion costs per GB
Example: 1TB logs → Hot $12/month → Archive $0.40/month (97% savings)
Phase 5: Backup & Retention
Enable soft delete (recover deleted blobs):
az storage account blob-service-properties update \
--account-name "st${app}${env}" \
--enable-delete-retention true \
--delete-retention-days 7
Enable versioning (keep blob history):
az storage account blob-service-properties update \
--account-name "st${app}${env}" \
--enable-versioning
# Now each write creates a new version
# Old versions kept until lifecycle policy deletes them
Immutable policy (WORM - write once, read many, for compliance):
# Set time-based retention
az storage blob properties update \
--account-name "st${app}${env}" \
--container-name "compliance" \
--name "audit.log" \
--set properties.immutabilityPolicy={expirationTime:\"2025-12-31T23:59:59Z\",policyMode:\"Locked\"}
# Blob cannot be deleted or modified until expiration
Phase 6: Monitoring & Alerting
Enable metrics & logging:
az storage logging update \
--account-name "st${app}${env}" \
--services b \
--log rwd \
--retention-days 30
Set alerts:
- Capacity > 80% of account quota
- Throttling (requests > per-second limit)
- Unusual deletion patterns
- Unauthorized access attempts
Output Contract
Storage Design
- Type selected (Blob, Files, Queues, ADLS) and justification
- Account creation commands
- Redundancy model (LRS, ZRS, GRS) and failover strategy
Security & Access
- Auth method (managed identity, SAS, keys) recommended
- Network isolation (private endpoints, firewalls)
- Encryption: at-rest (CMK or Microsoft-managed), in-transit (HTTPS)
Performance & Tiering
- Access tier choices (Hot/Cool/Archive/Cold)
- Lifecycle policy (automatic tiering rules)
- Cost estimation (hot vs. tiered vs. archive)
Backup & Retention
- Soft delete enabled? Versioning? Immutable retention?
- Lifecycle deletion policy
- RTO/RPO (can geo-failover if GRS)
Operational Checklist
- Monitoring enabled (metrics, logging)
- Alert thresholds set
- Cost optimization review cadence (quarterly)
Guardrails
- Prefer managed identity: No secrets in code; DefaultAzureCredential() handles token.
- Deny public access by default: Only allow explicit access (IP, VNet, SAS).
- Use lifecycle policies: Automatically move cold data to cheaper tiers; avoid manual re-tiering.
- Enable soft delete: Protects against accidental deletion; costs minimal.
- For compliance: Use immutable policies: Write-once-read-many (WORM) for audit logs.
- Monitor for throttling: If sustained >20,000 req/sec, consider sharding (multiple accounts).
- Audit access: Enable logging and monitor unexpected access patterns.
- Encrypt sensitive data: Use customer-managed keys (CMK) for highly regulated workloads.
1---2name: azure-storage3description: Design and operate Azure Storage services for durability, performance, and secure access. Use this skill when users ask about Blob, Files, Queues, Tables, or Data Lake storage patterns. Covers redundancy, tiering, access models, lifecycle policies, and compliance.4---56# Azure Storage78Select and configure Azure storage with optimal redundancy, performance tiering, and access controls.9Balance cost, durability, latency, and compliance requirements.1011## Use This Skill When1213- The user needs file, object, or queue storage in Azure14- The user needs lifecycle, replication, or retention policy design15- The user needs secure access model for storage workloads16- The user wants to optimize storage costs while maintaining SLA1718## Context: Storage Maturity1920**Immature**: Hot tier only, public access, no lifecycle, account key auth 21**Developing**: Correct tiering, RBAC, some lifecycle rules 22**Managed**: LRS for dev, GRS for prod, managed identity auth, lifecycle to cool/archive → **Target** 23**Optimized**: Geo-redundant reads, tiered access based on traffic, real-time cost optimization2425## Required Inputs2627- **Data type**: Documents, logs, video, database backups, transactional28- **Access pattern**: Frequent (hot), occasional (cool), rare (archive), cold29- **Size & growth**: 10GB initial, 10% monthly growth? Or 1TB spike?30- **Latency requirement**: <100ms or batch-oriented?31- **Durability**: RPO/RTO targets? Geographic redundancy needed?32- **Access model**: Public, private, user-scoped, application-only?33- **Compliance**: Data residency, encryption, retention, audit requirements?34- **Budget**: Cost-driven or performance-driven?3536## Decision Tree3738```39What type of data needs storage?40├─ Unstructured files (docs, images, video) → Blob Storage41├─ Shared file system (SMB/NFS for apps) → Azure Files42├─ Message queue → Queue Storage43├─ NoSQL key-value → Table Storage44├─ Big data analytics → Data Lake Storage45└─ Structured relational → SQL Database (not storage)4647How frequently is this data accessed?48├─ Daily (hot, <1 day SLA) → Hot tier ($0.012/GB/month)49├─ Weekly-monthly (cool, <30 day SLA) → Cool tier ($0.001/GB/month)50├─ Rarely, compliance hold (archive, <90 day SLA) → Archive tier ($0.0004/GB/month)51└─ Cold (7+ year retention) → Cold tier ($0.00099/GB/month)5253Do you need geographic failover?54├─ Single region (dev/test) → LRS (locally redundant, cheapest, 11x durability)55├─ Single region + replication → ZRS (zone redundant, same-region HA)56├─ Multi-region failover → GRS (geo-redundant, read from secondary)57└─ Multi-region read (active-active) → RA-GRS (read-access geo-redundant)5859How should apps access storage?60├─ Internal/private → Private endpoints, firewall rules61├─ Managed identity → System/user-assigned identity with role62├─ Public but controlled → SAS tokens (time-bound, scoped)63└─ Public read-only → Blob public access (for content CDN)64```6566## Workflow6768### Phase 1: Choose Storage Type & Account69701. **Create storage account**:71 ```bash72 az storage account create \73 --resource-group $RG \74 --name "st${app}${env}" \75 --location eastus \76 --kind StorageV2 \77 --sku Standard_GRS \78 --access-tier Hot \79 --https-only \80 --default-action Deny81 ```82832. **Configure networking** (private by default):84 ```bash85 # Block all public access86 az storage account update \87 --resource-group $RG \88 --name "st${app}${env}" \89 --public-network-access-enabled false90 91 # Or allow only specific IPs/VNets92 az storage account network-rule add \93 --resource-group $RG \94 --account-name "st${app}${env}" \95 --vnet-name $VNET \96 --subnet-name $SUBNET97 ```98993. **Enable encryption** (at-rest, in-transit):100 ```bash101 # HTTPS only (enforced above)102 # At-rest: Default Microsoft-managed keys OR customer-managed key (CMK)103 104 # Use CMK from Key Vault for sensitive data105 az storage account update \106 --resource-group $RG \107 --name "st${app}${env}" \108 --encryption-key-name "storage-cmk" \109 --encryption-key-vault $KV_ID110 ```111112### Phase 2: Create Containers/Shares & Set Tiering1131141. **For Blob Storage**:115 ```bash116 # Create container117 az storage container create \118 --account-name "st${app}${env}" \119 --name "documents" \120 --public-access off121 122 # Or create via Python/C#123 # container_client = blob_client.create_container(name="documents")124 ```1251262. **Set access tier** (per blob or policy-driven):127 ```bash128 # Set individual blob to cool tier129 az storage blob update \130 --account-name "st${app}${env}" \131 --container-name "documents" \132 --name "old-file.pdf" \133 --access-tier Cool134 ```1351363. **For Azure Files**:137 ```bash138 # Create file share139 az storage share create \140 --account-name "st${app}${env}" \141 --name "shared-files"142 143 # Create subdirectories144 az storage directory create \145 --account-name "st${app}${env}" \146 --share-name "shared-files" \147 --name "projects/2024"148 ```149150### Phase 3: Configure Access Controls1511521. **Using managed identity** (preferred):153 ```bash154 # App Service or AKS pod runs with managed identity155 # Assign role to identity156 PRINCIPAL_ID=$(az identity show --resource-group $RG --name $IDENTITY --query principalId -o tsv)157 158 az role assignment create \159 --role "Storage Blob Data Contributor" \160 --assignee-object-id $PRINCIPAL_ID \161 --scope "/subscriptions/$SUBID/resourceGroups/$RG/providers/Microsoft.Storage/storageAccounts/st${app}${env}"162 163 # In code: DefaultAzureCredential() fetches token automatically164 ```1651662. **Using SAS tokens** (time-bound, scoped):167 ```bash168 # Generate SAS token (expires in 1 hour)169 EXPIRY=$(date -u -d "+1 hour" +%Y-%m-%dT%H:%M:%SZ)170 171 az storage blob generate-sas \172 --account-name "st${app}${env}" \173 --container-name "documents" \174 --name "file.pdf" \175 --permissions r \176 --expiry $EXPIRY177 178 # Give user time-limited URL: https://storage.../file.pdf?sv=...&sig=...179 ```1801813. **Using account key** (not recommended for production):182 ```bash183 # Get account key184 KEY=$(az storage account keys list --resource-group $RG --account-name "st${app}${env}" --query "[0].value" -o tsv)185 186 # Connection string for legacy code187 CS="DefaultEndpointsProtocol=https;AccountName=st${app}${env};AccountKey=$KEY;EndpointSuffix=core.windows.net"188 189 # Store in Key Vault190 az keyvault secret set --vault-name $KV --name "storage-connection-string" --value "$CS"191 ```192193### Phase 4: Lifecycle Management1941951. **Create tiering policy**:196 ```json197 {198 "rules": [199 {200 "name": "auto-cool",201 "enabled": true,202 "type": "Lifecycle",203 "definition": {204 "filters": {205 "blobTypes": ["blockBlob"],206 "prefixMatch": ["logs/"]207 },208 "actions": {209 "baseBlob": {210 "tierToCool": { "daysAfterModificationGreaterThan": 30 },211 "tierToArchive": { "daysAfterModificationGreaterThan": 90 },212 "delete": { "daysAfterModificationGreaterThan": 365 }213 }214 }215 }216 }217 ]218 }219 ```220221 ```bash222 # Apply policy223 az storage account management-policy create \224 --account-name "st${app}${env}" \225 --resource-group $RG \226 --policy @lifecycle.json227 ```2282292. **Cost impact**:230 ```231 Hot tier: $0.012/GB/month232 Cool tier: $0.001/GB/month (83% savings)233 Archive: $0.0004/GB/month (97% savings)234 235 But: Archive = 4-hour retrieval, deletion costs per GB236 Example: 1TB logs → Hot $12/month → Archive $0.40/month (97% savings)237 ```238239### Phase 5: Backup & Retention2402411. **Enable soft delete** (recover deleted blobs):242 ```bash243 az storage account blob-service-properties update \244 --account-name "st${app}${env}" \245 --enable-delete-retention true \246 --delete-retention-days 7247 ```2482492. **Enable versioning** (keep blob history):250 ```bash251 az storage account blob-service-properties update \252 --account-name "st${app}${env}" \253 --enable-versioning254 255 # Now each write creates a new version256 # Old versions kept until lifecycle policy deletes them257 ```2582593. **Immutable policy** (WORM - write once, read many, for compliance):260 ```bash261 # Set time-based retention262 az storage blob properties update \263 --account-name "st${app}${env}" \264 --container-name "compliance" \265 --name "audit.log" \266 --set properties.immutabilityPolicy={expirationTime:\"2025-12-31T23:59:59Z\",policyMode:\"Locked\"}267 268 # Blob cannot be deleted or modified until expiration269 ```270271### Phase 6: Monitoring & Alerting2722731. **Enable metrics & logging**:274 ```bash275 az storage logging update \276 --account-name "st${app}${env}" \277 --services b \278 --log rwd \279 --retention-days 30280 ```2812822. **Set alerts**:283 - Capacity > 80% of account quota284 - Throttling (requests > per-second limit)285 - Unusual deletion patterns286 - Unauthorized access attempts287288## Output Contract2892901. **Storage Design**291 - Type selected (Blob, Files, Queues, ADLS) and justification292 - Account creation commands293 - Redundancy model (LRS, ZRS, GRS) and failover strategy2942952. **Security & Access**296 - Auth method (managed identity, SAS, keys) recommended297 - Network isolation (private endpoints, firewalls)298 - Encryption: at-rest (CMK or Microsoft-managed), in-transit (HTTPS)2993003. **Performance & Tiering**301 - Access tier choices (Hot/Cool/Archive/Cold)302 - Lifecycle policy (automatic tiering rules)303 - Cost estimation (hot vs. tiered vs. archive)3043054. **Backup & Retention**306 - Soft delete enabled? Versioning? Immutable retention?307 - Lifecycle deletion policy308 - RTO/RPO (can geo-failover if GRS)3093105. **Operational Checklist**311 - Monitoring enabled (metrics, logging)312 - Alert thresholds set313 - Cost optimization review cadence (quarterly)314315## Guardrails316317- **Prefer managed identity**: No secrets in code; DefaultAzureCredential() handles token.318- **Deny public access by default**: Only allow explicit access (IP, VNet, SAS).319- **Use lifecycle policies**: Automatically move cold data to cheaper tiers; avoid manual re-tiering.320- **Enable soft delete**: Protects against accidental deletion; costs minimal.321- **For compliance: Use immutable policies**: Write-once-read-many (WORM) for audit logs.322- **Monitor for throttling**: If sustained >20,000 req/sec, consider sharding (multiple accounts).323- **Audit access**: Enable logging and monitor unexpected access patterns.324- **Encrypt sensitive data**: Use customer-managed keys (CMK) for highly regulated workloads.