"I'm Using GRS...Aren't I Covered?" A Curious Question Met With The Reality of Azure Storage
- Shannon
- Sep 6
- 5 min read
This post came from a customer conversation that started with a seemingly innocent question:
“I’m using GRS for my storage accounts. Doesn’t that basically cover me if there’s a compelling event?”
On the surface, that feels like the right answer. Geo-Redundant Storage (GRS) replicates your data across regions. Six copies of your data, spread across hundreds of miles… it sounds like you’re bulletproof. But that’s where the discussion got interesting.
Redundancy != Resiliency
The customer assumed that GRS meant their application would keep running if a region failed. The reality: GRS guarantees durable copies of your data, not application continuity.
Here’s the nuanced outline out for you:
LRS (Locally Redundant Storage): Three copies in one datacenter. Cheap, but fragile.
ZRS (Zone-Redundant Storage): Data across three availability zones. Strong local protection.
GRS (Geo-Redundant Storage): Six copies (LRS + another LRS in a paired region). Durable, but secondary is passive unless you fail over.
RA-GRS: Same as GRS, but read-access in the secondary region.
GZRS / RA-GZRS: The best combo - zone redundancy and geo redundancy.
Reference: Azure Storage redundancy.
What I told them: “Your data is safe with GRS, but that doesn’t mean your app will magically work in the secondary region without some design work.”
Sidebar: The Math Behind the Magic – Erasure Coding in Azure
Customers often assume cloud durability means “three copies of everything, everywhere.” That’s only partly true. The real magic in Azure Storage durability is erasure coding (EC).
But what is erasure coding?
Here’s the simple version:
Your data is split into N chunks.
Azure adds a few parity chunks (think of them like extra puzzle pieces).
Those chunks are distributed across multiple storage nodes, racks, or even availability zones.
If a chunk is lost (disk failure, rack outage, or whatever), Azure can rebuild it using the parity chunks.
The math works out so that you don’t need all the chunks to recover the file, just enough to satisfy the parity equation.
Why does this matter? Well, it's durability at scale...instead of paying 3x overhead for full replication, erasure coding achieves the same or better durability with far less raw capacity consumed.
So when you buy GRS or ZRS, you’re not just getting “copies"...you’re getting copies plus math. And that math is what makes Azure’s durability promise possible across all storage SKUs! #themoreyouknow
How Resiliency Actually Works
Redundancy is about copies. Resiliency is about design. Join me for my continued TED talk!
If you want to survive a compelling event (region outage, datacenter fire, fiber cut), you need to think about:
Availability Zones: Deploying across multiple zones so you can survive a local outage.
Azure Site Recovery (ASR): Replicating entire VMs and apps to a paired region, with orchestrated failover.
Paired Regions: Every Azure region is paired for a reason — DR planning, patch sequencing, and replication.
Deep dive: Azure reliability documentation.
Helpful hint: Always check your RTO (Recovery Time Objective) and RPO (Recovery Point Objective) against what you’ve actually built. GRS doesn’t meet an RTO of zero. It just ensures the bits exist elsewhere.
Don’t Forget the Backup Safety Net
This is the part that usually gets an eye roll until I say it out loud: redundancy and resiliency are not backups.
Azure Backup covers you when:
Data corruption replicates to every copy.
A fat-finger deletes something important.
A ransomware attack encrypts your production data.
Reference: Azure Backup overview.
Pro tip: Test your restores. It’s not enough to set up a backup vault and assume it works. Do a dry run so you’re not the first person to learn your policy doesn’t align with business needs.
Enterprise Backup in the Cloud: Where All Your Favorite Backup Tools Sit!
When I talk to enterprise customers, the conversation about backup usually moves beyond just Azure Backup. Native tools are great for protecting Azure resources, but most large organizations live in a hybrid or multi-cloud reality. That’s where solutions like Commvault, Veeam, Rubrik, and Cohesity enter the picture.
Why enterprises lean this way:
Hybrid and Multi-Cloud Coverage: These tools don’t care if your workloads live in Azure, AWS, GCP, or on-prem VMware...they can apply a consistent backup policy across everything.
Granular Recovery: Need to restore a single mailbox, database table, or even a SharePoint site? Enterprise backup platforms go far beyond VM-level recovery.
Policy Consistency: Enterprises often need global retention rules, encryption standards, and compliance alignment. Third-party platforms give you one policy engine instead of juggling multiple native services.
Advanced Security: Many enterprise platforms add immutability, air-gapped storage, and even ransomware anomaly detection, which become extra safeguards you don’t always get natively.
Integration: These tools tie into existing ITSM workflows (ServiceNow, Remedy), monitoring platforms, and enterprise reporting systems, which is often non-negotiable at scale.
For large enterprises managing multi-petabyte environments across multiple clouds and data centers, native backup alone usually isn’t enough. That’s where enterprise-grade platforms come in. These solutions provide:
Policy-driven governance that ensures consistent retention and compliance rules across Azure, AWS, GCP, and on-prem.
Centralized control planes to manage backup and recovery from one place instead of juggling multiple portals.
Seamless integration with Azure Blob storage, often tiering backups into the cool or archive tiers for cost efficiency.
At that scale, the value isn’t just in storing backups...it’s in the reporting, governance, and consistency these platforms bring. For global enterprises, that centralized control is often worth the investment.
Bottom line:
For most mid-size orgs, Azure Backup is enough.
For large enterprises with compliance needs, complex recovery scenarios, or multi-cloud footprints, third-party backup software provides the extra guardrails and reporting that leadership and auditors expect.
The Layered Model
The way I explained it to the customer is as three concentric rings:
Redundancy (GRS, ZRS, etc.): Protects the data at rest.
Resiliency (AZs, ASR, paired regions): Keeps the app alive during outages.
Backups (Azure Backup, Recovery Services Vaults, Third Party Backup): Protect against corruption, deletion, or “everything went sideways.”
Only when you’ve got all three working together are you truly covered.
The Takeaway
When someone asks “Doesn’t GRS mean I’m basically covered?” the real answer is: “You’re partially covered.”
GRS gives you durability. Resiliency comes from how you design the app. And backups are the safety net that saves you when all else fails.
That’s the layered approach which turns “I think we’re fine” into real confidence.
The Final, Final Takeaway
It’s also one thing to talk about redundancy, resiliency, and backups. It’s another to see what’s actually happening in your tenant. A lot of customers ask me how they can quickly pull a catalog of their storage accounts and check usage.
Here’s a PowerShell script you can drop in as-is. It uses Azure Resource Graph (ARG) to discover all your Blob-enabled storage accounts, then calls Azure Monitor to pull the UsedCapacity metric. The result: a CSV inventory with account metadata and storage consumption in GB.
# Requires Az.ResourceGraph, Az.Monitor, Az.Accounts modules
# Step 1: Query ARG for all Blob-capable storage accounts
$storageAccounts = Search-AzGraph -Query @"
Resources
| where type == 'microsoft.storage/storageaccounts'
| where kind in~ ('StorageV2','BlobStorage')
| project id, name, resourceGroup, subscriptionId, location, skuName = tostring(sku.name), skuTier = tostring(sku.tier), accessTier = tostring(properties.accessTier), blobEndpoint = tostring(properties.primaryEndpoints.blob)
"@
# Step 2: Loop through accounts and pull UsedCapacity from Azure Monitor
$results = foreach ($acct in $storageAccounts) {
try {
$metric = Get-AzMetric -ResourceId $acct.id -MetricName "UsedCapacity" -TimeGrain 01:00:00 ` -ErrorAction Stop
$latest = $metric.Data | Where-Object { $_.Average -ne $null } | Select-Object -Last 1
[PSCustomObject]@{
SubscriptionId = $acct.subscriptionId
ResourceGroup = $acct.resourceGroup
Name = $acct.name
Location = $acct.location
SkuName = $acct.skuName
SkuTier = $acct.skuTier
AccessTier = $acct.accessTier
BlobEndpoint = $acct.blobEndpoint
UsedCapacityGB = if ($latest) { [math]::Round(($latest.Average / 1GB), 2) } else { 0 }
}
}
catch {
Write-Warning "Failed to get metrics for $($acct.name) in $($acct.resourceGroup)."
}
}
# Step 3: Display results
$results | Format-Table -AutoSize
# Step 4: Export to CSV if needed
$results | Export-Csv -Path "BlobStorageAccountInventory.csv" -NoTypeInformationIf you would like to copy/paste from GitHub, click here.
Happy storage day to you!
