Azure Storage
Azure Storage provides durable, highly available cloud storage for blobs, files, queues, and tables. It is the backbone for backups, media hosting, data lakes, static websites, and application messaging. Understanding account types, redundancy tiers, and access patterns is essential for cost-effective production deployments.
Storage Account Types
| Type | Supported Services | Use Case |
|---|---|---|
| General-purpose v2 | Blob, File, Queue, Table | Default choice for most workloads |
| Blob storage | Blob only (legacy) | Blob-only, no upgrades — avoid for new projects |
| Premium Block Blob | Blob (premium SSD) | Low-latency analytics, ML training data |
| Premium File Shares | File (premium) | SAP, high-IOPS enterprise file shares |
General-purpose v2 (StorageV2) supports hot/cool/cold/archive tiers, lifecycle management, and all four storage services. Always choose v2 unless you have a specific premium performance requirement.
Redundancy Options
| Option | Copies | Survives | Read Access in Secondary |
|---|---|---|---|
| LRS | 3 in one datacenter | Rack failure | No |
| ZRS | 3 across zones | Datacenter failure | No |
| GRS | 6 (3 primary + 3 secondary region) | Regional failure | Yes (RA-GRS) |
| GZRS | ZRS + geo-replication | Zone + regional failure | Yes (RA-GZRS) |
Production data that must survive regional outages should use GZRS or GRS. Dev/test workloads can use LRS to minimize cost.
Create a Storage Account
# Create account with secure defaults
az storage account create \
--name stwebappprod001 \
--resource-group rg-webapp-prod \
--location eastus \
--sku Standard_GZRS \
--kind StorageV2 \
--access-tier Hot \
--https-only true \
--min-tls-version TLS1_2 \
--allow-blob-public-access false
# Create blob containers
az storage container create \
--name uploads \
--account-name stwebappprod001 \
--auth-mode login
az storage container create \
--name backups \
--account-name stwebappprod001 \
--auth-mode login \
--public-access off
Blob Access Tiers
| Tier | Cost | Access Pattern | Minimum Retention |
|---|---|---|---|
| Hot | Higher storage, lower access | Frequently accessed | None |
| Cool | Lower storage, higher access | Infrequent (30+ days) | 30 days |
| Cold | Even lower storage | Rare (90+ days) | 90 days |
| Archive | Lowest storage | Long-term retention | 180 days |
Rehydrating from Archive takes hours (Standard) or up to 15 minutes (High priority, higher cost). Plan access patterns before tiering.
Lifecycle Management
Automate tier transitions and deletions with lifecycle policies:
# Create lifecycle policy JSON
cat > lifecycle-policy.json << 'EOF'
{
"rules": [
{
"name": "move-to-cool",
"type": "Lifecycle",
"definition": {
"filters": { "blobTypes": ["blockBlob"], "prefixMatch": ["uploads/"] },
"actions": {
"baseBlob": {
"tierToCool": { "daysAfterModificationGreaterThan": 30 },
"tierToArchive": { "daysAfterModificationGreaterThan": 365 },
"delete": { "daysAfterModificationGreaterThan": 2555 }
}
}
}
}
]
}
EOF
az storage account management-policy create \
--account-name stwebappprod001 \
--resource-group rg-webapp-prod \
--policy @lifecycle-policy.json
Upload, Download, and SAS Tokens
# Upload a blob
az storage blob upload \
--account-name stwebappprod001 \
--container-name uploads \
--name reports/2024-q4.pdf \
--file ./2024-q4.pdf \
--auth-mode login \
--tier Cool
# Generate time-limited SAS for client download
az storage blob generate-sas \
--account-name stwebappprod001 \
--container-name uploads \
--name reports/2024-q4.pdf \
--permissions r \
--expiry $(date -u -v+1H '+%Y-%m-%dT%H:%MZ') \
--auth-mode login \
--https-only
Python SDK example:
from azure.storage.blob import BlobServiceClient, generate_blob_sas, BlobSasPermissions
from datetime import datetime, timedelta
client = BlobServiceClient.from_connection_string(conn_str)
blob = client.get_blob_client(container="uploads", blob="photo.jpg")
with open("photo.jpg", "rb") as data:
blob.upload_blob(data, overwrite=True, standard_blob_tier="Hot")
# Download
with open("downloaded.jpg", "wb") as f:
f.write(blob.download_blob().readall())
Azure Files, Queues, and Tables
| Service | Protocol | Use Case |
|---|---|---|
| Azure Files | SMB/NFS | Lift-and-shift file shares, shared config |
| Queue Storage | REST API | Simple async messaging between services |
| Table Storage | REST/OData | NoSQL key-value, flexible schema |
# Create a file share (4 TiB max on standard tier)
az storage share create \
--name app-config \
--account-name stwebappprod001 \
--quota 100 \
--auth-mode login
# Mount on Linux VM
sudo mount -t cifs //stwebappprod001.file.core.windows.net/app-config /mnt/config \
-o vers=3.0,credentials=/etc/smbcredentials/stwebappprod001.cred,dir_mode=0777,file_mode=0777
Security
- Disable public blob access at the account level (default since 2021)
- Use private endpoints for VNet-only access — no traffic over public internet
- Apply RBAC (
Storage Blob Data Contributor) instead of shared keys when possible - Enable soft delete (blobs: 7–365 days) and versioning for recovery
- Use customer-managed keys (CMK) in Key Vault for compliance workloads
- Rotate access keys or prefer user delegation SAS with Entra ID
# Enable blob soft delete and versioning
az storage account blob-service-properties update \
--account-name stwebappprod001 \
--resource-group rg-webapp-prod \
--enable-delete-retention true \
--delete-retention-days 30 \
--enable-versioning true
Real-World Scenario: Media Platform
| Component | Configuration |
|---|---|
| Storage account | Standard_GZRS, Hot tier for active content |
| Containers | uploads (Hot), processed (Cool), archive (Archive) |
| CDN | Azure Front Door origin pointing to $web static container |
| Access | Private endpoint + RBAC for backend; SAS for direct uploads |
| Lifecycle | Hot → Cool after 30 days, Archive after 1 year |
| Monitoring | Diagnostic settings → Log Analytics; alerts on availability |
Storage vs Alternatives
| Feature | Blob Storage | Azure Files | Azure Data Lake Gen2 |
|---|---|---|---|
| Access | REST, SDK | SMB/NFS mount | REST + HDFS |
| Structure | Flat namespace | File hierarchy | Hierarchical (ACLs) |
| Best for | Objects, media, backups | Shared drives | Big data analytics |
| Cost | Tier-based | Capacity + transactions | Same as Blob + namespace |
Common Mistakes
- Using shared keys in application code — prefer Managed Identity and RBAC
- LRS for production backups — regional outage means data loss
- No lifecycle policy — Hot tier costs accumulate on stale data
- Public containers enabled — accidental data exposure
- Archive tier for data needed weekly — rehydration delays break SLAs
- Missing soft delete — accidental deletes are permanent without it
Troubleshooting
| Issue | Diagnosis | Fix |
|---|---|---|
| 403 AuthorizationFailure | Wrong key, expired SAS, or RBAC missing | Verify identity permissions; regenerate SAS |
| Slow uploads | Single-threaded, far from region | Use AzCopy with /J parallel; co-locate in same region |
| High transaction costs | Many small reads/writes | Batch operations; use CDN for static content |
| Cannot mount file share | Firewall blocks port 445 | Enable service endpoint or private endpoint |
| Replication lag | GRS async replication | Check RA-GRS read access; RPO typically < 15 min |
Best Practices
- Co-locate storage accounts with compute in the same region
- Use AzCopy or
az storage blob upload-batchfor large migrations - Enable diagnostic logs and set alerts on
Availabilitymetric < 100% - Tag accounts with
environment,cost-center, anddata-classification - Test restore procedures from soft delete and geo-redundant copies
- Use immutable blob storage (WORM) for compliance retention
Next: Azure Functions — Serverless.