Skip to content

Azure Storage Data Protection

AZ-104 Scott Duffy - Lecture 6 Storage

Overview

Azure Storage provides multiple layers of data protection to guard against accidental deletion, malicious tampering, and data corruption. These features work together as layered defenses: point-in-time restore, soft delete, versioning, change feed, and immutability. Understanding how they interrelate and their dependency chain is critical for the AZ-104 exam and real-world storage administration.


Point-in-Time Restore

Point-in-time restore allows you to restore an entire container (or a subset of blobs) to a specific previous state within a defined restoration window.

Key Facts

  • Maximum restoration window: 30 days
  • Can restore an entire container to a specified date and time
  • Example scenario: Restore to the state from 21 days ago to recover from bulk accidental changes

Prerequisites -- All Three Required

Point-in-time restore requires all of the following to be enabled simultaneously:

  1. Versioning -- must be on
  2. Change feed -- must be on
  3. Blob soft delete -- must be on

If any one of these is disabled, point-in-time restore cannot function.

txt
direction: right

pitr: Point-in-Time Restore {
  style.fill: "#2ecc71"
  style.font-color: "#fff"
  style.stroke: "#27ae60"
}

versioning: Versioning {
  style.fill: "#f39c12"
  style.font-color: "#fff"
  style.stroke: "#e67e22"
}

change_feed: Change Feed {
  style.fill: "#9b59b6"
  style.font-color: "#fff"
  style.stroke: "#8e44ad"
}

soft_delete: Blob Soft Delete {
  style.fill: "#3498db"
  style.font-color: "#fff"
  style.stroke: "#2980b9"
}

pitr -> versioning: requires {
  style.stroke: "#e74c3c"
  style.font-color: "#e74c3c"
}
pitr -> change_feed: requires {
  style.stroke: "#e74c3c"
  style.font-color: "#e74c3c"
}
pitr -> soft_delete: requires {
  style.stroke: "#e74c3c"
  style.font-color: "#e74c3c"
}

How It Works

When point-in-time restore is triggered, Azure uses the change feed log to replay blob state back to the target timestamp. The versioning system provides the actual blob data at each point, and soft delete ensures that deleted blobs are still recoverable within the window.

SettingValue
Max restore window30 days
GranularityContainer or blob prefix
Required featuresVersioning + Change Feed + Soft Delete
Storage account typeGeneral-purpose v2

Data Protection tab showing point-in-time restore and soft delete options


Soft Delete

Soft delete is a safety net that marks blobs, containers, or file shares as deleted rather than permanently removing them. This provides a configurable grace period during which deleted data can be recovered.

Default Behavior

  • Enabled by default on new storage accounts
  • Default retention: 7 days (configurable up to 365 days)
  • Deleted items are retained in a soft-deleted state and do not appear in normal listings

Three Variants of Soft Delete

VariantScopeWhat It Protects
Blob soft deleteIndividual blobs and snapshotsRecover accidentally deleted and overwritten blobs
Container soft deleteEntire containersRecover deleted containers and all their contents
File share soft deleteAzure file sharesRecover deleted file shares

Soft delete settings for containers and file shares

Soft Delete Protects Against Overwrites (Not Just Deletes)

This Is NOT the Same as Versioning

Blob soft delete protects against both deletion and overwrites. When a blob is overwritten, the previous version is saved as a soft-deleted snapshot that can be recovered within the retention window. This is a distinct mechanism from versioning:

  • Soft delete on overwrite: The previous blob state is saved as a soft-deleted snapshot with a retention period. It is automatically purged after the retention window expires.
  • Versioning on overwrite: The previous blob state is saved as a permanent version that persists until explicitly deleted or removed by lifecycle policy.

Both protect against accidental overwrites, but they work differently:

AspectSoft Delete (Overwrite)Versioning
What gets savedSoft-deleted snapshotPermanent version
RetentionTime-limited (7-365 days)Indefinite until deleted
Auto-cleanupYes, after retention expiresNo, must use lifecycle rules
Cost impactTemporary (storage during retention)Ongoing (all versions persist)
Recovery methodUndelete / list soft-deleted snapshotsAccess by version ID

From Microsoft Learn -- Soft delete for blobs:

"When blob soft delete is enabled for a storage account, you can recover blobs, blob versions, and snapshots after they are deleted, within a retention period that you specify. Blob soft delete also preserves the overwritten state of a blob by maintaining a soft-deleted snapshot of the blob's previous state."

Impact on Testing and Development

Soft delete can complicate testing workflows. When you delete test files, they are not actually removed -- they persist in a soft-deleted state. To truly remove them you must either:

  • Wait for the retention period to expire
  • Purge the soft-deleted items manually

This is a common gotcha when scripting cleanup of test environments.

Recovery Process

When a blob is soft-deleted (via deletion or overwrite), it can be recovered by calling the Undelete Blob operation. For overwrites, the previous state is saved as a soft-deleted snapshot that can be listed and restored. The blob returns to its active state with all its properties and metadata intact.


Versioning

Versioning automatically maintains previous versions of blobs every time they are modified or overwritten. Each version is an immutable snapshot of the blob at the time of the write operation.

How It Works

  • Every modification creates a new version automatically
  • Example: A file updated every 30 days will accumulate versions (v6, v7, v8, etc.)
  • Previous versions are read-only and immutable
  • Useful for audit trails and accidental modification recovery

Versioning and change feed configuration options

Version Browsing in Practice

Blob versioning in practice -- multiple versions listed

Blob properties showing version details

Cost Implications -- Critical for Exam and Production

You pay for each version stored. Storage costs multiply based on update frequency:

  • A blob updated daily with versioning enabled will store 30 versions per month
  • Depending on update frequency, versioning can increase storage costs by 2x to 10x
  • Use lifecycle management policies to move old versions to cooler tiers (Cool, Cold, Archive) or delete them after a retention period

Lifecycle Management for Versions

You can configure lifecycle management rules to automatically transition or delete old versions:

ActionExample Rule
Move to Cool tierVersions older than 30 days
Move to Archive tierVersions older than 90 days
Delete old versionsVersions older than 365 days

Change Feed

The change feed provides a transaction log of all create, modify, and delete operations on blobs in a storage account. It is stored in the $blobchangefeed container.

Change Feed Details

  • Logs all create, modify, and delete operations on blobs
  • Format: Apache Avro (compact binary format)
  • Can be consumed by listening to the feed or querying it
  • Enables event-driven actions based on changes
  • Use cases: compliance auditing, automation pipelines, alerting

Change Feed vs Event Grid

FeatureChange FeedEvent Grid
Delivery modelPull (poll/query)Push (event subscription)
Data formatApache AvroJSON (CloudEvents)
RetentionConfigurableTransient
OrderingGuaranteed per blobBest effort
Use caseAudit, compliance, replayReal-time reactions

Immutability

Immutability ensures that once a blob is written, it cannot be altered or deleted for a specified retention period. This implements WORM (Write Once Read Many) storage.

Immutability Is Irreversible (When Locked)

Once an immutability policy is locked, it cannot be decreased or removed. Blobs under a locked policy cannot be deleted even by the storage account owner or an Azure administrator. Plan retention periods carefully.

Configuration Levels

LevelScopeNotes
Account-levelApplies to all containersBroadest scope
Container-levelApplies to all blobs in the containerMost common configuration
Version-levelApplies to specific blob versionsRequires versioning enabled

Policy Types

Time-Based Retention Policy

  • Blobs cannot be modified or deleted for a specified number of days
  • Policy can be unlocked (modifiable) or locked (immutable itself)
  • Once locked, the retention period can only be increased, never decreased
  • Blobs cannot be modified or deleted until the legal hold is explicitly cleared
  • No expiration date -- remains until removed
  • Multiple legal holds can be applied (identified by tags)
  • Use case: Litigation, investigations, regulatory holds
FeatureTime-Based RetentionLegal Hold
DurationFixed period (days)Indefinite until cleared
Can be removed?Only if unlockedYes, by clearing the hold
ExpirationAutomatic after periodManual removal only
Multiple policiesOne per containerMultiple tags supported

Compliance Standards

Immutable storage meets the requirements for:

  • SEC Rule 17a-4(f) -- Securities and Exchange Commission
  • FINRA Rule 4511 -- Financial Industry Regulatory Authority
  • CFTC Rule 1.31 -- Commodity Futures Trading Commission
  • WORM compliance (Write Once Read Many)

Use Cases

  • Security logs that cannot be tampered with
  • Compliance records for financial services
  • Audit trails for regulated industries
  • Evidence preservation -- prevents malicious deletion
  • Healthcare records (HIPAA)

Immutability Requires Versioning

When versioning is enabled alongside immutability, the policy applies to all blob versions. This ensures that even previous versions of a blob are protected from deletion or modification.


Blob Lifecycle State Diagram


CLI and PowerShell Commands

bash
# Enable soft delete for blobs with 14-day retention
az storage blob service-properties delete-policy update \
  --account-name myaccount \
  --enable true \
  --days-retained 14

# Enable versioning
az storage account blob-service-properties update \
  --account-name myaccount \
  --resource-group myRG \
  --enable-versioning true

# Enable change feed
az storage account blob-service-properties update \
  --account-name myaccount \
  --resource-group myRG \
  --enable-change-feed true

# Create a time-based immutability policy (365 days)
az storage container immutability-policy create \
  --account-name myaccount \
  --container-name mycontainer \
  --period 365

# Lock an immutability policy (IRREVERSIBLE)
az storage container immutability-policy lock \
  --account-name myaccount \
  --container-name mycontainer \
  --if-match "<ETag>"

# Set a legal hold
az storage container legal-hold set \
  --account-name myaccount \
  --container-name mycontainer \
  --tags "litigation2026"

# Undelete a soft-deleted blob
az storage blob undelete \
  --account-name myaccount \
  --container-name mycontainer \
  --name myblob.txt

# List blob versions
az storage blob list \
  --account-name myaccount \
  --container-name mycontainer \
  --include v \
  --output table
powershell
# Enable soft delete for blobs with 14-day retention
Enable-AzStorageBlobDeleteRetentionPolicy `
  -ResourceGroupName "myRG" `
  -StorageAccountName "myaccount" `
  -RetentionDays 14

# Enable versioning
Update-AzStorageBlobServiceProperty `
  -ResourceGroupName "myRG" `
  -StorageAccountName "myaccount" `
  -IsVersioningEnabled $true

# Enable change feed
Update-AzStorageBlobServiceProperty `
  -ResourceGroupName "myRG" `
  -StorageAccountName "myaccount" `
  -EnableChangeFeed $true

# Create a time-based immutability policy (365 days)
Set-AzStorageContainerImmutabilityPolicy `
  -ResourceGroupName "myRG" `
  -StorageAccountName "myaccount" `
  -ContainerName "mycontainer" `
  -ImmutabilityPeriod 365

# Lock an immutability policy (IRREVERSIBLE)
Lock-AzStorageContainerImmutabilityPolicy `
  -ResourceGroupName "myRG" `
  -StorageAccountName "myaccount" `
  -ContainerName "mycontainer" `
  -Etag "<ETag>"

# Set a legal hold
Add-AzStorageContainerLegalHold `
  -ResourceGroupName "myRG" `
  -StorageAccountName "myaccount" `
  -ContainerName "mycontainer" `
  -Tag "litigation2026"

# Undelete a soft-deleted blob
$ctx = New-AzStorageContext -StorageAccountName "myaccount" -StorageAccountKey "<key>"
Get-AzStorageBlob -Context $ctx -Container "mycontainer" -Blob "myblob.txt" -IncludeDeleted |
  Restore-AzStorageBlob

Lab Exercise

Hands-On Lab: Data Protection Features

Prerequisites

  • An Azure subscription
  • A General-purpose v2 storage account
  • Azure CLI or PowerShell installed

Step 1 -- Enable Soft Delete with 14-Day Retention

bash
az storage blob service-properties delete-policy update \
  --account-name <your-account> \
  --enable true \
  --days-retained 14

Verify in the portal under Storage Account > Data protection.

Step 2 -- Upload, Delete, and Recover a Blob

bash
# Create a test file
echo "Hello, data protection!" > testfile.txt

# Upload the blob
az storage blob upload \
  --account-name <your-account> \
  --container-name testcontainer \
  --name testfile.txt \
  --file testfile.txt

# Delete the blob
az storage blob delete \
  --account-name <your-account> \
  --container-name testcontainer \
  --name testfile.txt

# List soft-deleted blobs
az storage blob list \
  --account-name <your-account> \
  --container-name testcontainer \
  --include d \
  --output table

# Recover the soft-deleted blob
az storage blob undelete \
  --account-name <your-account> \
  --container-name testcontainer \
  --name testfile.txt

Step 3 -- Enable Versioning and Browse Versions

bash
# Enable versioning
az storage account blob-service-properties update \
  --account-name <your-account> \
  --resource-group <your-rg> \
  --enable-versioning true

# Upload a file
echo "Version 1 content" > versiontest.txt
az storage blob upload \
  --account-name <your-account> \
  --container-name testcontainer \
  --name versiontest.txt \
  --file versiontest.txt \
  --overwrite

# Modify and re-upload
echo "Version 2 content" > versiontest.txt
az storage blob upload \
  --account-name <your-account> \
  --container-name testcontainer \
  --name versiontest.txt \
  --file versiontest.txt \
  --overwrite

# List all versions
az storage blob list \
  --account-name <your-account> \
  --container-name testcontainer \
  --include v \
  --output table

Step 4 -- Enable Change Feed and Observe Entries

bash
# Enable change feed
az storage account blob-service-properties update \
  --account-name <your-account> \
  --resource-group <your-rg> \
  --enable-change-feed true

# Perform some blob operations (upload, modify, delete)
# Then check the $blobchangefeed container for Avro-format logs
az storage blob list \
  --account-name <your-account> \
  --container-name '$blobchangefeed' \
  --output table

Note: Change feed entries may take a few minutes to appear.

Step 5 -- Create Immutability Policy and Test Deletion

bash
# Create a time-based immutability policy (1 day for testing)
az storage container immutability-policy create \
  --account-name <your-account> \
  --container-name immutablecontainer \
  --period 1

# Upload a blob to the immutable container
echo "This cannot be deleted" > immutable.txt
az storage blob upload \
  --account-name <your-account> \
  --container-name immutablecontainer \
  --name immutable.txt \
  --file immutable.txt

# Attempt to delete the blob (THIS SHOULD FAIL)
az storage blob delete \
  --account-name <your-account> \
  --container-name immutablecontainer \
  --name immutable.txt

Expected output: The delete operation should fail with an error indicating the blob is protected by an immutability policy.

Cleanup

bash
# Remove the legal hold / unlock policy before deleting resources
# Delete the test storage account or containers when finished

Microsoft Learn References

TopicLink
Point-in-Time RestoreOverview
Blob Soft DeleteOverview
Blob VersioningOverview
Immutable StorageOverview
Change FeedOverview

Summary

FeaturePurposeDefaultKey Requirement
Point-in-Time RestoreRestore container to prior stateDisabledVersioning + Change Feed + Soft Delete
Soft DeleteGrace period before permanent removalEnabled (7 days)None
VersioningAutomatic version history on modificationDisabledNone
Change FeedTransaction log of all blob operationsDisabledNone
ImmutabilityWORM -- prevent modification and deletionDisabledVersioning (for version-level)

Released under the MIT License.