01What Is Azure Storage Account?
Azure Storage Account is Microsoft Azure's foundational, massively scalable cloud storage service. It's the backbone of almost every Azure solution β storing files, database backups, IoT telemetry, web assets, message queues, and structured data. A single account is a top-level container for multiple services: Blob, Queue, Table, and File.
02Storage Account Types
Azure offers several storage account kinds, each optimized for different workloads and performance requirements. Choosing the right type impacts cost, available services, and throughput guarantees. Use this comparison when provisioning new accounts or evaluating whether a Premium tier is justified for your latency-sensitive workloads.
| Kind | Services | Use Case |
|---|---|---|
| General Purpose v2 (GPv2) | Blob, Queue, Table, File | β Default β use for everything |
| Premium Block Blobs | Blob only | Low-latency blob ops (< 1ms) |
| Premium File Shares | File only | SMB/NFS with SSD performance |
| Premium Page Blobs | Page Blobs only | Azure VM Managed Disks |
03Storage Services Overview
A single storage account bundles multiple services, each designed for a distinct data shape and access pattern. Understanding the capacity limits and ideal use cases helps you pick the right service without over-engineering. Refer to this table when designing new features or migrating existing data stores to Azure.
| Service | Shape | Max Size | Use Case |
|---|---|---|---|
| Blob | Objects in containers | 5 PiB account, 190.7 TiB per blob | Images, videos, backups, logs |
| Queue | FIFO messages | 500 TB account, 64 KB per message | Task queues, decoupling |
| Table | NoSQL key-value rows | 500 TB | Entity data, device state, config |
| File | SMB/NFS share | 100 TiB per share, 4 TiB per file | Lift-and-shift file shares |
| Data Lake Gen2 | Hierarchical namespace | Same as Blob | Big data, Spark, Synapse |
04Blob Storage β Deep Dive
Blob Storage is the most widely used Azure storage service, handling everything from static assets to multi-terabyte backups. It supports three blob types optimized for different I/O patterns, and offers rich SDK operations for upload, download, and access control. Master these fundamentals for any production workload that stores unstructured data.
Blob Types
| Type | Description | Use Case |
|---|---|---|
| Block Blob | Made of blocks (up to 50,000 Γ 4000 MB) | Files, images, videos, backups β most common |
| Append Blob | Blocks can only be appended, not modified | Log files, audit trails |
| Page Blob | Random read/write, 512-byte pages | VM disks, databases needing random I/O |
SDK Operations β .NET
var serviceClient = new BlobServiceClient("connection-string");
var containerClient = serviceClient.GetBlobContainerClient("my-container");
await containerClient.CreateIfNotExistsAsync(PublicAccessType.None);
// Upload with metadata
var blobClient = containerClient.GetBlobClient("folder/file.json");
await blobClient.UploadAsync(
BinaryData.FromString("{\"id\": 1}"),
new BlobUploadOptions
{
Metadata = new Dictionary<string, string> { ["env"] = "prod" },
Tags = new Dictionary<string, string> { ["project"] = "myapp" },
HttpHeaders = new BlobHttpHeaders { ContentType = "application/json" }
});
// Download
BlobDownloadResult result = await blobClient.DownloadContentAsync();
string content = result.Content.ToString();
// Generate SAS URL (1 hour read-only)
Uri sasUri = blobClient.GenerateSasUri(
BlobSasPermissions.Read,
DateTimeOffset.UtcNow.AddHours(1));
// List blobs
await foreach (BlobItem blob in containerClient.GetBlobsAsync())
Console.WriteLine($"{blob.Name} β {blob.Properties.ContentLength} bytes");Container Access Levels
| Level | Description |
|---|---|
| Private (default) | No anonymous access β authentication always required |
| Blob | Anonymous read for individual blobs only β no listing |
| Container | Anonymous read + list all blobs in container |
Blob Versioning & Soft Delete
# Enable soft delete (30-day retention)
az storage blob service-properties delete-policy update \
--account-name mystorageaccount \
--enable true --days-retained 30
# Enable versioning
az storage account blob-service-properties update \
--account-name mystorageaccount \
--enable-versioning true05Queue Storage β Deep Dive
Azure Queue Storage is a simple, cost-effective message queue for asynchronous communication. Messages are up to 64KB, retained up to 7 days, and use a visibility timeout model.
var queueClient = new QueueClient("connection-string", "my-queue");
await queueClient.CreateIfNotExistsAsync();
// Enqueue
await queueClient.SendMessageAsync("Hello, World!");
// Enqueue with 30s visibility delay
await queueClient.SendMessageAsync(
"Delayed task",
visibilityTimeout: TimeSpan.FromSeconds(30),
timeToLive: TimeSpan.FromHours(1));
// Dequeue (peek-lock)
QueueMessage[] messages = await queueClient.ReceiveMessagesAsync(maxMessages: 10);
foreach (var msg in messages)
{
Console.WriteLine($"Message: {msg.MessageText}");
// Process...
await queueClient.DeleteMessageAsync(msg.MessageId, msg.PopReceipt);
}
// Get queue depth
QueueProperties props = await queueClient.GetPropertiesAsync();
Console.WriteLine($"Approx count: {props.ApproximateMessagesCount}");06Table Storage β Deep Dive
Azure Table Storage is a serverless NoSQL key-value store. Entities have aPartitionKey + RowKey as primary key, plus up to 255 custom properties per entity.
var tableClient = new TableClient("connection-string", "Employees");
await tableClient.CreateIfNotExistsAsync();
// Insert entity
var emp = new TableEntity("Engineering", "emp001")
{
["Name"] = "Alice",
["Role"] = "Developer",
["Age"] = 30
};
await tableClient.AddEntityAsync(emp);
// Query (OData filter)
var results = tableClient.QueryAsync<TableEntity>(
filter: TableClient.CreateQueryFilter(
$"PartitionKey eq 'Engineering' and Age gt {25}"));
await foreach (var entity in results)
Console.WriteLine($"{entity["Name"]} β {entity["Role"]}");
// Upsert (insert or replace)
await tableClient.UpsertEntityAsync(emp);
// Delete
await tableClient.DeleteEntityAsync("Engineering", "emp001");PartitionKey Design
| Strategy | Example | Notes |
|---|---|---|
| By entity type | Customer, Order | Simple, risk of hot partitions |
| By date | 2025-01, 2025-02 | Good for time-series range queries |
| By region | EU, US, AP | Geographic distribution |
| By tenant | tenantId value | Ideal for multi-tenant SaaS apps |
| By hash prefix | a3f-customerId | Distributes load across partitions evenly |
07Azure File Share
Fully managed cloud file shares accessible via SMB 3.x, NFS 4.1, and the FileREST API. Mount as a network drive on Windows or Linux, or in Docker/AKS as a PersistentVolume.
Mount on Linux
sudo apt install cifs-utils
sudo mount -t cifs //mystorageaccount.file.core.windows.net/myshare /mnt/myshare \
-o vers=3.0,username=mystorageaccount,\
password=<storageAccountKey>,dir_mode=0777,file_mode=0777Mount on Windows
net use Z: \\mystorageaccount.file.core.windows.net\myshare \
/user:Azure\mystorageaccount <storageAccountKey>08Data Lake Storage Gen2
ADLS Gen2 = Blob Storage + Hierarchical Namespace. It enables atomic directory rename, POSIX ACLs, and the ABFS protocol used by Spark, Databricks, and Synapse Analytics.
| Feature | Standard Blob | ADLS Gen2 |
|---|---|---|
| Namespace | Flat | Hierarchical (true directories) |
| Rename | Copy + Delete (slow) | Atomic rename (fast) |
| POSIX ACLs | β No | β Yes |
| Protocol | REST, HTTPS | REST + HDFS/ABFS |
| Analytics | Basic | Optimized β Spark, Databricks, Synapse |
# Enable at creation (cannot change later)
az storage account create \
--name mydatalake \
--resource-group myRG \
--kind StorageV2 \
--enable-hierarchical-namespace trueABFS URI Format
# Azure Blob File System URI
abfs://<container>@<account>.dfs.core.windows.net/<path>
# Example
abfs://raw-data@mydatalake.dfs.core.windows.net/2025/01/sales.parquet09Access Tiers
Access tiers let you balance storage cost against retrieval cost based on how frequently data is accessed. Choosing the right tier can reduce storage bills by up to 80% for infrequently accessed data. Use lifecycle policies to automate tier transitions as data ages in production.
| Tier | Storage Cost | Access Cost | Min Duration | Retrieval |
|---|---|---|---|---|
| π₯ Hot | Highest | Lowest | None | Instant |
| βοΈ Cool | Lower | Higher | 30 days | Instant |
| π§ Cold | Lower still | Higher | 90 days | Instant |
| π¦ Archive | Lowest | Highest | 180 days | 1β15 hours (rehydrate) |
Rehydrate from Archive
// Start rehydration (High priority = ~1 hour)
await blobClient.SetAccessTierAsync(
AccessTier.Hot,
rehydratePriority: RehydratePriority.High);
// Check status
BlobProperties props = await blobClient.GetPropertiesAsync();
Console.WriteLine(props.ArchiveStatus); // "rehydrate-pending-to-hot"10Redundancy & Replication
Redundancy determines how many copies of your data exist and where they are stored, directly impacting durability and availability SLAs. The right choice depends on your disaster recovery requirements and budget constraints. Select geo-redundant options for mission-critical data that must survive a full regional outage.
| Option | Copies | Zones | Regions | Read Secondary | Durability |
|---|---|---|---|---|---|
| LRS | 3 | 1 | 1 | β No | 11 nines |
| ZRS | 3 | 3 | 1 | β No | 12 nines |
| GRS | 6 | 1 | 2 | After failover only | 16 nines |
| GZRS | 6 | 3+1 | 2 | After failover only | 16 nines |
| RA-GRS | 6 | 1 | 2 | β Yes | 16 nines |
| RA-GZRS | 6 | 3+1 | 2 | β Yes | 16 nines |
11Security & Authentication
Azure Storage supports multiple authentication methods ranging from shared keys to Entra ID RBAC. Choosing the right method is critical for production security β leaked account keys grant full access to all data. Prefer Managed Identity and RBAC for service-to-service communication, and use SAS tokens only for time-limited external access.
| Method | Type | Recommended? |
|---|---|---|
| Account Key | Full access shared key | β οΈ Only for admin/migration |
| SAS Token | Scoped, time-limited key | β For external client access |
| Managed Identity | Entra ID token, no secrets | β Recommended for services |
| RBAC (Entra ID) | Role-based token | β Recommended for users |
RBAC Roles
| Role | Permissions |
|---|---|
Storage Blob Data Owner | Full blob + ACL management |
Storage Blob Data Contributor | Read, write, delete blobs |
Storage Blob Data Reader | Read blobs only |
Storage Queue Data Contributor | Read, write, delete messages |
Storage Table Data Contributor | Read, write, delete entities |
Disable Shared Key Access
# Force Entra ID only β disables all account key + SAS key auth
az storage account update \
--name mystorageaccount \
--resource-group myRG \
--allow-shared-key-access false12Network Security
Network-level controls restrict which clients can reach your storage account, adding defense-in-depth beyond authentication. In production, always deny public access by default and whitelist only trusted IPs, VNets, or private endpoints. This prevents data exfiltration even if credentials are compromised.
Firewall & IP Rules
# Deny all public access by default
az storage account update \
--name mystorageaccount --resource-group myRG \
--default-action Deny
# Allow specific IP CIDR
az storage account network-rule add \
--account-name mystorageaccount \
--ip-address 203.0.113.0/24
# Allow VNet subnet
az storage account network-rule add \
--account-name mystorageaccount \
--vnet-name myVNet --subnet mySubnet
# Allow trusted Azure services to bypass
az storage account update \
--name mystorageaccount --bypass AzureServices13Lifecycle Management Policies
Automatically transition blobs between tiers or delete them based on age, last-access time, or blob index tags β saving significant cost on cold/archive data.
{
"rules": [{
"name": "tiering-rule",
"enabled": true,
"type": "Lifecycle",
"definition": {
"filters": {
"blobTypes": ["blockBlob"],
"prefixMatch": ["logs/", "backups/"]
},
"actions": {
"baseBlob": {
"tierToCool": { "daysAfterModificationGreaterThan": 30 },
"tierToCold": { "daysAfterModificationGreaterThan": 90 },
"tierToArchive": { "daysAfterModificationGreaterThan": 180 },
"delete": { "daysAfterModificationGreaterThan": 365 }
},
"snapshot": { "delete": { "daysAfterCreationGreaterThan": 90 } },
"version": { "delete": { "daysAfterCreationGreaterThan": 90 } }
}
}
}]
}14Shared Access Signatures (SAS)
SAS tokens provide fine-grained, time-limited access to storage resources without exposing account keys. They are essential for granting external clients or partner systems temporary access to specific blobs or containers. Always prefer User Delegation SAS backed by Entra ID for the highest security, as they can be revoked by rotating the delegation key.
| Type | Backed By | Scope | Security Level |
|---|---|---|---|
| Account SAS | Account Key | Multiple services | Medium |
| Service SAS | Account Key | Single service/container/blob | Medium |
| User Delegation SAS | Entra ID token | Blob/ADLS only | β Highest |
Generate SAS β .NET
// Service SAS β read-only blob for 1 hour
BlobSasBuilder sasBuilder = new BlobSasBuilder
{
BlobContainerName = "images",
BlobName = "profile.jpg",
Resource = "b", // b=blob, c=container
ExpiresOn = DateTimeOffset.UtcNow.AddHours(1)
};
sasBuilder.SetPermissions(BlobSasPermissions.Read);
Uri sasUri = blobClient.GenerateSasUri(sasBuilder);
// User Delegation SAS (Entra ID backed β most secure)
UserDelegationKey delegationKey = await blobServiceClient
.GetUserDelegationKeyAsync(
DateTimeOffset.UtcNow,
DateTimeOffset.UtcNow.AddHours(4));SAS URL Anatomy
https://account.blob.core.windows.net/images/photo.jpg
?sv=2023-01-03 β Storage version
&st=2025-01-01T10:00Z β Start time
&se=2025-01-01T11:00Z β Expiry time
&sr=b β Resource (b=blob, c=container)
&sp=r β Permissions (r=read, w=write, d=delete, l=list)
&sip=203.0.113.0/24 β Allowed IP range (optional)
&spr=https β HTTPS only
&sig=<signature> β HMAC-SHA25615Encryption
Azure Storage encrypts all data at rest and in transit by default, requiring zero configuration for baseline protection. For regulated industries, Customer Managed Keys and infrastructure encryption provide additional control and auditability over key rotation. Use CMK when compliance mandates that your organization retains sole control of encryption keys.
| Type | Description | Default? |
|---|---|---|
| Encryption at rest | AES-256 for all data on disk | β Always on |
| Encryption in transit | HTTPS / TLS 1.2+ | β Enforced |
| Microsoft Managed Keys (MMK) | Azure manages the encryption keys | β Default |
| Customer Managed Keys (CMK) | Your keys in Key Vault or HSM | Optional β compliance |
| Infrastructure Encryption | Double-encrypt at hardware layer | Optional β max security |
# Enable CMK with Key Vault
az storage account update \
--name mystorageaccount \
--encryption-key-source Microsoft.Keyvault \
--encryption-key-vault https://myKeyVault.vault.azure.net \
--encryption-key-name storage-encryption-key
# Enforce HTTPS-only + TLS 1.2
az storage account update \
--name mystorageaccount \
--https-only true \
--min-tls-version TLS1_216Function Apps Integration
Azure Functions integrates natively with Storage through triggers and bindings, enabling event-driven architectures with minimal boilerplate. Blob triggers react to file uploads, queue triggers process messages, and output bindings write results β all without managing connections manually. Use these patterns to build scalable, serverless data pipelines in production.
Blob Trigger
[FunctionName("ProcessUpload")]
public static async Task Run(
[BlobTrigger("uploads/{name}", Connection = "AzureWebJobsStorage")]
Stream blobStream,
string name,
BlobClient blobClient,
ILogger log)
{
log.LogInformation($"Blob {name} uploaded. Size: {blobStream.Length}");
BlobProperties props = await blobClient.GetPropertiesAsync();
// Process...
}Queue Trigger
[FunctionName("ProcessQueueMessage")]
public static void Run(
[QueueTrigger("task-queue", Connection = "AzureWebJobsStorage")]
string message, ILogger log)
{
log.LogInformation($"Queue message: {message}");
}Blob Output Binding
[FunctionName("GenerateReport")]
[return: Blob("reports/{DateTime}.json", Connection = "AzureWebJobsStorage")]
public static string Run([TimerTrigger("0 0 * * * *")] TimerInfo timer)
{
return JsonSerializer.Serialize(new { GeneratedAt = DateTime.UtcNow });
}Table Output Binding
[FunctionName("LogEvent")]
public static async Task Run(
[HttpTrigger] HttpRequest req,
[Table("AuditLog", Connection = "AzureWebJobsStorage")]
IAsyncCollector<TableEntity> table)
{
await table.AddAsync(new TableEntity("2025-01", Guid.NewGuid().ToString())
{
["EventType"] = "UserLogin",
["IpAddress"] = req.HttpContext.Connection.RemoteIpAddress?.ToString()
});
}17Logic Apps Integration
Logic Apps provides low-code connectors for Azure Storage, enabling workflow automation without writing custom code. These connectors support polling triggers for blob changes and actions for CRUD operations on blobs, queues, and tables. Use Logic Apps integration when you need rapid workflow prototyping or when non-developers manage the integration logic.
| Action / Trigger | Description |
|---|---|
| When a blob is added or modified | Trigger Logic App on blob change (polling) |
| Create blob | Upload a blob from workflow |
| Get blob content | Download blob body as workflow variable |
| Get blob metadata | Read properties, tags, content type |
| List blobs | Enumerate container contents |
| Delete blob | Remove a blob from container |
| Copy blob | Server-side copy between containers |
| Extract archive to folder | Unzip archive blob to Blob Storage |
Storage Blob Data Contributor to the Logic App's system identity. Consumption Logic Apps use Connection String.18APIM Integration
Azure API Management can proxy storage operations, adding rate limiting, authentication, and request transformation in front of Blob Storage. This pattern exposes storage as a managed API without giving clients direct access to storage credentials. Use it when external consumers need controlled upload/download capabilities through your API gateway.
APIM β Upload Blob (Managed Identity)
<inbound>
<base />
<authentication-managed-identity
resource="https://storage.azure.com/"
output-token-variable-name="storageToken" />
<send-request mode="new"
response-variable-name="uploadResult" timeout="60">
<set-url>@($"https://{{account}}.blob.core.windows.net/uploads/{context.Request.MatchedParameters["filename"]}")</set-url>
<set-method>PUT</set-method>
<set-header name="Authorization" exists-action="override">
<value>@("Bearer " + (string)context.Variables["storageToken"])</value>
</set-header>
<set-header name="x-ms-blob-type" exists-action="override">
<value>BlockBlob</value>
</set-header>
<set-header name="x-ms-version" exists-action="override">
<value>2023-01-03</value>
</set-header>
<set-body>@(context.Request.Body.As<string>())</set-body>
</send-request>
<return-response response-variable-name="uploadResult" />
</inbound>19Other Azure Services
20Monitoring & Alerts
Proactive monitoring of storage metrics helps detect capacity issues, latency degradation, and unauthorized access before they impact users. Azure Monitor provides built-in metrics and diagnostic logs for all storage services. Configure alerts on key thresholds to enable rapid incident response in production environments.
| Metric | Description | Alert Condition |
|---|---|---|
| UsedCapacity | Total storage used | > 80% of quota |
| Ingress / Egress | Data transfer bytes | Unusual egress spike |
| Availability | Success rate % | < 99.9% |
| SuccessE2ELatency | End-to-end latency | > 1000ms |
| Transactions | API requests per interval | Spike detection |
| BlobCount | Number of blobs | Lifecycle policy check |
KQL β Unauthorized Access Attempts
StorageBlobLogs
| where StatusCode == 403
| summarize count() by CallerIpAddress, OperationName
| order by count_ desc21Static Website Hosting
Azure Storage can serve static websites directly from the $web container, eliminating the need for a separate web server. This is ideal for SPAs, documentation sites, and marketing pages with minimal operational overhead. Pair with Azure CDN for custom domains, HTTPS, and global edge caching in production.
# Enable static website hosting
az storage blob service-properties update \
--account-name mystorageaccount \
--static-website \
--index-document index.html \
--404-document 404.html
# Upload build output to $web container
az storage blob upload-batch \
--account-name mystorageaccount \
--source ./dist \
--destination '$web'
# URL: https://mystorageaccount.z6.web.core.windows.net/22vs Service Bus / Event Hubs
Azure offers multiple messaging and storage services that overlap in certain scenarios, making it important to understand their strengths. This comparison helps you decide whether Storage Queue suffices or whether you need Service Bus's advanced features like sessions and dead-lettering. Use this table when architecting event-driven systems to pick the right service for each communication pattern.
| Capability | Blob | Queue | Table | File | Service Bus | Event Hubs |
|---|---|---|---|---|---|---|
| Store large files | β Yes | β No | β No | β Yes | β No | β No |
| Key-value store | β No | β No | β Yes | β No | β No | β No |
| Task queuing | β No | β Yes | β No | β No | β YesPlus | β No |
| Pub-Sub | β No | β No | β No | β No | β Yes | β Yes |
| Event streaming | β No | β No | β No | β No | β No | β Yes |
| FIFO ordering | β No | β No | β No | β No | Sessions | Partition-level |
| SMB mount | β No | β No | β No | β Yes | β No | β No |
| Price | β Cheapest | β Cheapest | β Cheapest | Medium | Higher | Medium |
23Architecture Patterns
24Quick Reference Cheat Sheet
Blob: https://<account>.blob.core.windows.net
Queue: https://<account>.queue.core.windows.net
Table: https://<account>.table.core.windows.net
File: https://<account>.file.core.windows.net
DFS: https://<account>.dfs.core.windows.net
Web: https://<account>.z<N>.web.core.windows.net# Create storage account
az storage account create \
--name mystorageaccount --resource-group myRG \
--location eastus --sku Standard_GRS --kind StorageV2
# Upload blob
az storage blob upload \
--file ./data.json --container-name mycontainer \
--name data.json --account-name mystorageaccount
# Generate SAS URL
az storage blob generate-sas \
--account-name mystorageaccount \
--container-name mycontainer --name data.json \
--permissions r --expiry 2025-12-31T00:00Z --https-only --output tsv
# Queue message
az storage message put \
--queue-name myqueue --content "Hello" --account-name mystorageaccount| Limit | Value |
|---|---|
| Storage accounts per subscription per region | 250 |
| Max storage account capacity | 5 PiB |
| Max block blob size | ~4.77 TiB |
| Max blob name length | 1,024 chars |
| Max queue message size | 64 KB |
| Max queue message TTL | 7 days |
| Max table entity size | 1 MB |
| Max table entity properties | 255 |
| Max file share size | 100 TiB |