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

  1. Using shared keys in application code — prefer Managed Identity and RBAC
  2. LRS for production backups — regional outage means data loss
  3. No lifecycle policy — Hot tier costs accumulate on stale data
  4. Public containers enabled — accidental data exposure
  5. Archive tier for data needed weekly — rehydration delays break SLAs
  6. 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-batch for large migrations
  • Enable diagnostic logs and set alerts on Availability metric < 100%
  • Tag accounts with environment, cost-center, and data-classification
  • Test restore procedures from soft delete and geo-redundant copies
  • Use immutable blob storage (WORM) for compliance retention

Next: Azure Functions — Serverless.