Nutshell Series

Unit of Work Pattern in a Nutshell

The Unit of Work Pattern is used to save multiple database changes as one single transaction.

It makes sure that either all changes are saved or none of them are saved.

Simple Example

When placing an order, the system may need to:

  • Create an order
  • Reduce product stock
  • Save payment details

If one step fails, the other changes should not be saved. Unit of Work helps manage this safely.

Key Idea

Do multiple operations
Save everything once

C# Example

public interface IUnitOfWork
{
    Task SaveChangesAsync();
}
public class UnitOfWork : IUnitOfWork
{
    private readonly AppDbContext _context;

    public UnitOfWork(AppDbContext context)
    {
        _context = context;
    }

    public async Task SaveChangesAsync()
    {
        await _context.SaveChangesAsync();
    }
}

Usage

product.Stock -= 1;

orderRepository.Add(order);

await unitOfWork.SaveChangesAsync();

In EF Core

In Entity Framework Core, DbContext already works like a Unit of Work because it tracks changes and saves them together using:

await dbContext.SaveChangesAsync();

Conclusion

Unit of Work means collect all changes first, then save them together once.

Nutshell Series

How to Optimize GitHub Copilot Usage After June 2026 Changes

GitHub Copilot usage started draining faster for many users after the June 2026 billing changes. The main reason is that Copilot moved toward usage-based billing with GitHub AI Credits.

In simple terms: your usage now depends more on the model you choose, the amount of context, and whether you use features like Chat, Agent Mode, Code Review, CLI, Spaces, Spark, or cloud agents.

What Changed?

  • Copilot now uses AI Credits for many advanced features.
  • Normal code completions and next edit suggestions are still included in paid plans.
  • Premium models consume more credits.
  • Agent mode and code review can drain usage quickly.
  • Claude Sonnet 4.6 can be much more expensive than older models in some plans.

Why Usage Drains Fast

Copilot can consume more credits when it receives large context, scans multiple files, generates long answers, or uses premium models. Agent mode is especially expensive because it may perform multiple steps, inspect files, edit code, and retry.

How to Reduce Copilot Usage

1. Do Not Use Premium Models for Everything

Use cheaper/default models for normal coding, explanations, small refactors, and unit test skeletons. Save premium models for hard debugging, architecture, and complex multi-file issues.

2. Avoid Agent Mode for Small Changes

Do not use agent mode for simple fixes. Use normal chat with selected code instead.

Use only the selected code.
Find the bug.
Show only the minimal fix.
Do not scan the full workspace.

3. Keep Context Small

Select only the method, class, or error message Copilot needs. Avoid asking it to inspect the whole project unless required.

4. Limit Output

Ask Copilot to keep answers short.

Show only changed lines.
Do not rewrite the full file.
Keep the answer under 10 lines.

5. Use Autocomplete More

For daily coding, rely more on Copilot autocomplete and next edit suggestions. Use Chat only when you need reasoning or explanation.

6. Use Code Review Carefully

Copilot code review can consume significant usage. Use it for important PRs, not every small change.

7. Set a Budget

Check your Copilot billing settings and set a small overage limit. Start with a low cap before allowing extra usage.

Recommended Workflow

Autocomplete → daily coding
Default model → small questions
Premium model → hard debugging
Agent mode → only for real multi-file work
Code review → only for important PRs

Final Takeaway

GitHub Copilot is still powerful, but after the June 2026 changes, it should be used more intentionally. Keep prompts small, avoid premium models by default, and reserve agent mode for complex tasks.

Best rule: use the cheapest useful mode first, then move to premium models only when needed.

Nutshell Series

Strategy Pattern Explained in Simple Terms

The Strategy Pattern is a way to keep different behaviours separate instead of putting everything inside one big if/else block.

In simple words:

Strategy Pattern means choosing the right way to do something at runtime.

Layman Example

Imagine you want to travel to office.

You have different options:

  • Walk
  • Take a bus
  • Drive a car
  • Take a train

The goal is the same: reach the office.

But the method, or strategy, is different.

Software Example

Suppose an application needs to calculate delivery charges.

  • Standard delivery has one rule
  • Express delivery has another rule
  • Free delivery has another rule

Without Strategy Pattern, we may write everything in one method using many conditions.

if (deliveryType == "Standard")
{
    // standard delivery logic
}
else if (deliveryType == "Express")
{
    // express delivery logic
}
else if (deliveryType == "Free")
{
    // free delivery logic
}

This works, but as the rules grow, the code becomes harder to read and maintain.

How Strategy Pattern Helps

With Strategy Pattern, each rule is moved into its own class.

  • StandardDeliveryStrategy
  • ExpressDeliveryStrategy
  • FreeDeliveryStrategy

Each class handles only one behaviour.

The main code simply chooses the correct strategy and uses it.

Implementation Example

First, create a common interface for all delivery charge strategies.

public interface IDeliveryChargeStrategy
{
    decimal Calculate();
}

Now create separate classes for each strategy.

public class StandardDeliveryStrategy : IDeliveryChargeStrategy
{
    public decimal Calculate()
    {
        return 5;
    }
}

public class ExpressDeliveryStrategy : IDeliveryChargeStrategy
{
    public decimal Calculate()
    {
        return 15;
    }
}

public class FreeDeliveryStrategy : IDeliveryChargeStrategy
{
    public decimal Calculate()
    {
        return 0;
    }
}

Now choose the correct strategy based on the delivery type.

public class DeliveryChargeCalculator
{
    public decimal Calculate(string deliveryType)
    {
        IDeliveryChargeStrategy strategy = deliveryType switch
        {
            "Standard" => new StandardDeliveryStrategy(),
            "Express" => new ExpressDeliveryStrategy(),
            "Free" => new FreeDeliveryStrategy(),
            _ => throw new ArgumentException("Invalid delivery type")
        };

        return strategy.Calculate();
    }
}

Usage:

var calculator = new DeliveryChargeCalculator();

var charge = calculator.Calculate("Express");

Console.WriteLine(charge); // 15

Why Use It?

  • Code becomes cleaner
  • Large if/else blocks are reduced
  • Each behaviour is easier to change
  • Each rule can be tested separately
  • New behaviours can be added without disturbing old ones

When to Use It?

Use Strategy Pattern when the same action can be done in different ways.

Common examples:

  • Payment methods
  • Discount calculation
  • Delivery charge calculation
  • File export formats
  • Notification sending
  • Data update rules

In a Nutshell

The Strategy Pattern helps us separate different ways of doing the same thing.

Instead of writing one large method with many conditions, we create separate classes for each behaviour and choose the right one when needed.

Nutshell Series

Why Azure Function App Deployments Fail Randomly and How to Fix Them

Azure Function App deployments can sometimes fail randomly even when the deployment log says the package was deployed successfully.

This commonly happens with ZIP Deploy, Run From Package, and .NET isolated Azure Functions. The package deployment completes, but the post-deployment validation fails after several minutes.

Typical Symptoms

  • Deployment takes 10–15 minutes and then fails
  • Kudu log shows Deployment successful
  • Azure DevOps still reports deployment failure
  • The Function App URL is available
  • The issue is random and succeeds on retry

Example Deployment Log

Deployment successful.
deployer = VSTS_ZIP_DEPLOY_FUNCTIONS_V2
deploymentPath = Functions App ZipDeploy. Run from package.

Error: Package deployment using ZIP Deploy failed.

This log is confusing because the ZIP package deployment succeeded, but the Azure DevOps task failed later during validation.

Why This Happens

After the ZIP package is deployed, Azure performs additional steps:

  1. Recycle the Function App
  2. Start the Function host
  3. Load dependencies
  4. Sync triggers
  5. Validate runtime health

If any of these steps are slow, blocked, or unstable, Azure DevOps may mark the deployment as failed even though the package was uploaded successfully.

Common Root Causes

1. Slow Function Host Startup

.NET isolated Azure Functions can take longer to start if the app has:

  • Heavy dependency injection setup
  • Many Service Bus or Event Hub triggers
  • Expensive startup logic
  • Slow Key Vault or managed identity calls
  • Large dependency graph

2. Kudu or SCM Instability

The deployment may complete successfully, but the Kudu/SCM site may become slow or unstable during validation.

This can cause Azure DevOps to report a deployment failure even when the Function App has received the new package.

3. Storage Account Latency

Azure Functions depend heavily on the storage account configured in AzureWebJobsStorage.

If the storage account has firewall, private endpoint, DNS, or throttling issues, the Function host may fail or delay startup.

4. Unhealthy Worker Node

Sometimes the Function App may be running on an unhealthy or overloaded Azure worker node.

This can cause random issues such as:

  • Slow deployments
  • Failed deployment validation
  • Long Function host startup time
  • Intermittent Kudu failures

5. Overlapping Deployments

If multiple pipelines deploy to the same Function App at the same time, file locks, recycle conflicts, or validation failures can occur.

How to Fix or Reduce the Issue

1. Use Run From Package

Ensure the Function App uses Run From Package:

WEBSITE_RUN_FROM_PACKAGE=1

This avoids direct file copy issues and makes deployments more reliable.

2. Disable Remote Build

If the pipeline already publishes the application, disable remote build in Azure:

SCM_DO_BUILD_DURING_DEPLOYMENT=false
ENABLE_ORYX_BUILD=false

This prevents Kudu from trying to rebuild the application during deployment.

3. Restart Before Deployment

A restart before deployment can clear stuck runtime or SCM state:

az functionapp restart \
  --name <function-app-name> \
  --resource-group <resource-group-name>

4. Add Retry in Azure DevOps

Because this issue is often intermittent, add retry logic to the deployment task:

retryCountOnTaskFailure: 3

5. Optimize .NET Isolated Startup

Reduce startup time by:

  • Avoiding heavy logic in Program.cs
  • Lazy-loading external clients
  • Reducing reflection-heavy scanning
  • Minimizing synchronous startup calls
  • Checking Key Vault and managed identity delays

6. Check Storage Account Connectivity

Verify that the storage account used by AzureWebJobsStorage is healthy and reachable.

Check for:

  • Firewall restrictions
  • Private endpoint DNS issues
  • Storage throttling
  • Network latency

7. Force App Service Plan Infrastructure Refresh

You cannot directly choose a physical machine in Azure, but you can force the app to move to different infrastructure indirectly.

Common options include:

  • Scale out and then scale in
  • Scale up to a higher SKU and then scale down
  • Restart the Function App
  • Move to a new App Service Plan

This can help when the app is running on an unhealthy or overloaded worker node.

8. Avoid Parallel Deployments

Ensure only one deployment runs against the Function App at a time.

Parallel deployments can cause recycle conflicts, validation failures, and inconsistent deployment results.

How to Confirm Deployment Actually Succeeded

Check the Kudu deployment history:

https://<function-app-name>.scm.azurewebsites.net/api/deployments

If the latest deployment status is successful, then the package deployment completed. The failure is likely happening during runtime startup or validation.

In Short

When Azure DevOps reports that ZIP Deploy failed, but Kudu shows Deployment successful, the issue is usually not the package upload itself.

Most of the time, the real cause is:

  • Slow Function host startup
  • Kudu or SCM instability
  • Storage account latency
  • Unhealthy App Service worker node
  • Post-deployment validation timeout

The best practical fixes are to enable Run From Package, optimize startup, add deployment retry, check storage connectivity, and force an App Service Plan infrastructure refresh when needed.

Nutshell Series

Software Architectures Explained (Quick & Practical Guide)

If you’re building applications in .NET or any backend stack, understanding architecture is critical. Here’s a concise guide to the most important software architectures.


1. Layered Architecture (N-Tier)

Structure:

Controller → Service → Repository → Database
  • Pros: Simple, easy to implement
  • Cons: Tight coupling, harder to scale
  • Best for: Small to medium applications

2. Clean Architecture

Idea: Dependencies always point inward. Business logic is independent.

UI → Application → Domain → Infrastructure
  • Pros: Highly testable, maintainable
  • Cons: More boilerplate
  • Best for: Enterprise systems

3. Onion Architecture

Idea: Domain is at the center, everything depends on it.

    Domain (Core)
 Application Layer
Infrastructure Layer
  • Pros: Strong domain focus
  • Cons: Learning curve
  • Best for: Domain-driven applications

4. Hexagonal Architecture (Ports & Adapters)

Idea: Isolate core logic using interfaces (ports) and implementations (adapters).

Adapters → Ports → Core Domain → Ports → Adapters
  • Pros: Decoupled, testable
  • Cons: More abstraction
  • Best for: Maintainable systems, microservices

5. Monolithic Architecture

Idea: Entire application in a single codebase.

  • Pros: Simple deployment
  • Cons: Hard to scale
  • Best for: Startups, MVPs

6. Microservices Architecture

Idea: Break system into independent services.

User Service | Order Service | Payment Service
  • Pros: Scalable, independent deployments
  • Cons: Complex (network, monitoring)
  • Best for: Large distributed systems

7. Event-Driven Architecture

Idea: Components communicate via events.

OrderPlaced → PaymentProcessed → EmailSent
  • Pros: Loose coupling, scalable
  • Cons: Hard debugging
  • Best for: Real-time systems

8. CQRS (Command Query Responsibility Segregation)

Idea: Separate read and write operations.

  • Pros: Performance optimization
  • Cons: Added complexity
  • Best for: High-scale systems

9. Domain-Driven Design (DDD)

Idea: Design software based on business domain.

  • Key concepts: Entities, Value Objects, Aggregates
  • Best for: Complex business logic systems

10. Serverless Architecture

Idea: Run code without managing servers.

  • Pros: Auto-scaling, cost-efficient
  • Cons: Cold starts, debugging challenges
  • Best for: Cloud-native apps

11. Modular Monolith

Idea: Single app, but divided into well-structured modules.

  • Pros: Balance of simplicity and structure
  • Cons: Requires discipline
  • Best for: Growing applications

Quick Summary

  • Small apps: Layered / Monolith
  • Growing apps: Modular Monolith
  • Enterprise: Clean / Hexagonal
  • Large scale: Microservices + Event-driven

Start simple. Add complexity only when needed. The right architecture depends on your scale, team, and business needs.

Nutshell Series

gRPC in Simple Terms (Modern RPC)

gRPC is a modern way for applications to talk to each other in distributed systems. It is the latest evolution of RPC (Remote Procedure Call) designed for speed, efficiency, and scalability.

Simply put:

gRPC allows one service to call another service’s function just like calling a local method — but faster and smarter for cloud systems.

What is gRPC?

gRPC is a communication framework that helps different services exchange data efficiently.

Think of it like:

Calling a function in another computer as if it is in your own code.

It is widely used in:

  • Microservices
  • Cloud applications
  • Real-time systems
  • High-performance backend systems

How gRPC Works (Simple Flow)

  1. Developer defines service in a .proto file
  2. gRPC generates client and server code automatically
  3. Client sends request in binary format (small & fast)
  4. Communication happens using HTTP/2
  5. Server processes and sends response

Why gRPC is Faster

gRPC is fast because:

  • Uses binary data instead of JSON
  • Uses HTTP/2 instead of HTTP/1
  • Supports streaming
  • Uses strong contracts

This makes it ideal for internal service communication.

Types of gRPC Communication

  • Unary → One request → One response
  • Server Streaming → One request → Many responses
  • Client Streaming → Many requests → One response
  • Bidirectional Streaming → Many ↔ Many

This is useful for:

  • Live tracking apps
  • Chat systems
  • Financial streaming data
  • IoT systems

gRPC vs REST

Feature gRPC REST
Speed Very Fast Medium
Data Format Binary JSON
Streaming Yes Limited
Best For Internal Microservices Public APIs
Human Readable No Yes

Advantages of gRPC

  • Very high performance
  • Small payload size
  • Strong typing reduces runtime errors
  • Built for microservices
  • Supports real-time streaming

Challenges

  • Harder to debug compared to REST
  • Not directly supported in browsers
  • Requires learning Protocol Buffers

Simple Real-World Example

Imagine an e-commerce system:

  • Order Service calls Payment Service → gRPC
  • Website calls Backend API → REST

This provides:

  • Fast internal communication
  • Simple external integration

Conclusion

gRPC is the modern evolution of RPC, designed for cloud-native and microservices architectures. It helps systems communicate faster, more efficiently, and at large scale.

As distributed systems continue to grow, gRPC is becoming a standard choice for internal service communication.

Nutshell Series

Cold vs Hot Observables in Rx.NET

Reactive Extensions (Rx.NET) is used to handle asynchronous data streams in .NET applications.
One of the most important concepts to understand is the difference between Cold Observables and Hot Observables.


What is an Observable?

An Observable is a data stream that we can subscribe to and receive values over time.

IObservable<int> stream = Observable.Range(1, 3);
stream.Subscribe(x => Console.WriteLine(x));

Cold Observables (Simple Meaning)

  • Starts only when someone subscribes
  • Each subscriber gets separate execution
  • Default behavior in Rx.NET
  • Best used for API calls, database queries, file reading

Simple Cold Observable Example

var cold = Observable.Range(1, 3);

cold.Subscribe(x => Console.WriteLine("Subscriber 1: " + x));
cold.Subscribe(x => Console.WriteLine("Subscriber 2: " + x));

Here execution happens twice because each subscriber gets a new stream.


Hot Observables (Simple Meaning)

  • Runs continuously and shares data
  • All subscribers receive the same live stream
  • Execution happens only once
  • Best used for event streams, real-time systems, UI events

Simple Hot Observable Example

var hot = Observable.Interval(TimeSpan.FromSeconds(1))
                    .Publish()
                    .RefCount();

hot.Subscribe(x => Console.WriteLine("Subscriber 1: " + x));
hot.Subscribe(x => Console.WriteLine("Subscriber 2: " + x));

Now both subscribers share the same execution.


Even Simpler Way Using Share()

var hot = Observable.Interval(TimeSpan.FromSeconds(1))
                    .Share();

Share() is a shortcut for Publish().RefCount().


Real Life Example

  • Cold Observable: Watching a recorded video separately
  • Hot Observable: Watching live TV broadcast

Cold vs Hot Comparison

Feature Cold Hot
Execution Per subscriber Shared
Data Type Fresh data Live data
Performance Lower Higher
Use Case API / Database Streaming

Best Practices

  • Use Cold Observables for request-based operations
  • Use Hot Observables for real-time streaming
  • Share expensive operations to avoid duplicate execution

Conclusion

Understanding Cold vs Hot Observables is essential for building scalable reactive applications.
Choosing the correct type helps avoid duplicate processing and improves system performance.

Technology: Rx.NET | Reactive Programming

Nutshell Series

Fixing “Value cannot be null. (Parameter ‘provider’)” Error While Running Azure Function Apps Locally

While developing Azure Function Apps locally, you may encounter the runtime error:

Value cannot be null. (Parameter 'provider')

This issue can be frustrating because it appears during startup and often looks like a coding problem. However, in most cases, it is caused by local tooling or runtime installation issues.

🚨 Problem

When running the Function App locally using:

func start

The runtime fails with:

Value cannot be null. (Parameter 'provider')

This typically happens:

  • After updating SDKs or runtime
  • When Azure Functions Core Tools is outdated or corrupted
  • After switching runtime models (in-process → isolated)
  • When dependencies are partially installed
  • After environment setup changes

🔍 Root Cause

This error is generally caused by:

  • Broken or outdated Azure Functions Core Tools installation
  • Runtime dependency mismatch
  • Corrupted local function runtime cache
  • Improper SDK/runtime configuration

Essentially, the Azure Functions runtime fails to initialize its internal service provider. This is a tooling/runtime problem — not your application code.

✅ Recommended Fix — Reinstall Azure Functions Local Runtime

The most reliable fix is to completely reinstall Azure Functions Core Tools and local runtime components.

Follow official Microsoft guide:


Run Azure Functions locally – Microsoft Docs

🧹 Step 1 — Remove Existing Installation

If installed via npm:

npm uninstall -g azure-functions-core-tools

If installed via MSI:

  • Go to Control Panel → Programs & Features
  • Remove Azure Functions Core Tools
  • Restart your system

📦 Step 2 — Install Latest Version

npm install -g azure-functions-core-tools@4 --unsafe-perm true

This ensures:

  • Correct runtime initialization
  • Updated dependency providers
  • Compatibility with latest Azure Functions SDK

🔄 Step 3 — Clean Local Function Cache

Delete these folders if present:

.azurefunctions
bin
obj

Then rebuild:

dotnet build
func start

📌 Additional Troubleshooting

  • Ensure correct .NET SDK version is installed
  • Verify isolated vs in-process configuration
  • Check Functions Core Tools version:
func --version
  • Update Azure Functions VS Code extension
  • Clear NuGet cache:
dotnet nuget locals all --clear

🧠 Key Takeaway

Most “Value cannot be null. (provider)” errors occur due to:

  • Broken local runtime installation
  • Outdated Azure Functions Core Tools

Reinstalling the runtime is often the fastest and most reliable fix.

🚀 Conclusion

If your Function App fails locally with provider null error:

  • Do not debug business logic first
  • Fix local runtime environment
  • Reinstall using official Microsoft guidance

This approach can save hours of debugging and restore local execution immediately.

Nutshell Series

Azure Blob Storage Tiers Explained: Hot, Cool, Cold, Archive, and Premium

Azure Blob Storage offers multiple storage tiers that allow you to store data in a cost-effective way
based on how frequently the data is accessed and how quickly it needs to be retrieved.
Choosing the right tier helps balance performance, availability, and cost.

Azure Storage Performance Tiers

Azure Blob Storage provides two performance tiers:

  • Premium performance tier
  • Standard performance tier

Premium Storage Tier

Premium storage is optimized for mission-critical and high-performance applications.
It provides low latency and high throughput.

  • Currently available only for Block Blob storage
  • Uses SSD-based storage
  • Designed for workloads requiring consistent low latency
  • Higher cost compared to standard tiers

Standard Storage Access Tiers

The Standard performance tier (available with GPv2 storage accounts) supports multiple access tiers
that are optimized for different data access patterns.

Hot Storage Tier

Hot storage is optimized for data that is accessed frequently.

  • Lowest access costs
  • Higher storage costs compared to other standard tiers
  • Best for active data and frequently accessed objects
  • Highest availability SLA among standard tiers

Cool Storage Tier

Cool storage is optimized for data that is accessed infrequently and stored for at least 30 days.

  • Lower storage costs than Hot tier
  • Higher access costs compared to Hot tier
  • Slightly lower availability SLA than Hot tier
  • Ideal for short-term backups and disaster recovery data

Cold Storage Tier (New)

Cold storage is designed for data that is rarely accessed but still needs to remain online.
It provides a lower-cost option than Cool storage while maintaining online accessibility.

  • Lower storage costs than Cool tier
  • Higher access costs than Cool tier
  • Minimum storage duration of 90 days
  • Data remains online and accessible without rehydration
  • Ideal for long-term retention data accessed occasionally

Archive Storage Tier

Archive storage is optimized for data that is rarely accessed and stored for long periods.
It provides the lowest storage cost but with higher access latency.

  • Lowest storage cost of all tiers
  • Data is stored offline
  • Highest data access costs
  • Minimum storage duration of 180 days
  • Data retrieval requires rehydration and can take hours

Storage Tier Scope and Limitations

  • The Hot and Cool tiers can be set at the storage account level.
  • The Archive tier cannot be set at the account level.
  • Hot, Cool, Cold, and Archive tiers can be set at the blob (object) level.
  • The Archive tier is available only at the blob level.

Key Considerations When Choosing a Tier

  • Hot tier prioritizes performance and availability.
  • Cool tier trades slightly lower availability and higher access cost for lower storage cost.
  • Cold tier provides lower storage cost while keeping data online.
  • Archive tier minimizes storage cost but requires rehydration and higher access latency.

Summary

  • Premium – High-performance workloads requiring low latency.
  • Hot – Frequently accessed data.
  • Cool – Infrequently accessed data stored for at least 30 days.
  • Cold – Rarely accessed data stored for at least 90 days.
  • Archive – Long-term data stored for at least 180 days with flexible access latency.

By selecting the appropriate storage tier, organizations can significantly reduce costs
while meeting performance and availability requirements.

Nutshell Series

Azure Blob Storage: Block, Append, and Page Blobs Explained

Azure Blob Storage provides three types of blobs designed for different workloads:
Block Blobs, Append Blobs, and Page Blobs.
Each blob type is optimized for specific data access patterns and storage requirements.

Block Blobs

Block blobs are designed for efficient upload and storage of large amounts of unstructured data such as documents, images, videos, and backups.

  • Data is stored as blocks identified by unique block IDs.
  • Blocks are uploaded independently and committed together to create or update a blob.
  • Supports up to 50,000 blocks.
  • Modern service versions support block sizes up to 4,000 MiB (≈4 GB).
  • Maximum block blob size can exceed 190 TiB.
  • Smaller block blobs can be uploaded using a single write operation.

Legacy Limits (Older REST Versions)

  • Maximum block size: 100 MB
  • Maximum blob size: approximately 4.75 TB
  • Older REST versions supported 4 MB blocks with a maximum size of around 195 GB

Page Blobs

Page blobs are optimized for random read and write operations and are similar to disk storage.
They are commonly used for virtual machine disks.

  • Data is stored in 512-byte pages.
  • Supports random access using offset and range aligned to 512-byte boundaries.
  • Writes occur in-place and are immediately committed.
  • Individual pages or multiple pages (up to 4 MB) can be updated at once.
  • Maximum page blob size is 8 TiB.

Append Blobs

Append blobs are optimized for scenarios where data is continuously added to the end of a blob, such as logging and auditing.

  • Built using blocks but support append-only operations.
  • Existing blocks cannot be modified or deleted.
  • Block IDs are not exposed.
  • Each block can be up to 4 MB.
  • Supports up to 50,000 blocks.
  • Maximum append blob size is approximately 195 GB.

Choosing the Right Blob Type

  • Block Blob – Files, media, backups, and general storage.
  • Append Blob – Logs, telemetry, and audit trails.
  • Page Blob – VM disks and random read/write workloads.

How the Blob Type Is Specified

The blob type must be specified at the time of creation and cannot be changed later.
Applications, SDKs, CLI tools, or Azure services explicitly define the blob type.

Using REST API

x-ms-blob-type: BlockBlob | AppendBlob | PageBlob

Using Azure CLI

Azure CLI allows you to specify the blob type when creating or uploading a blob.

Create a Block Blob (default)

az storage blob upload \
  --account-name mystorageaccount \
  --container-name data \
  --name file.txt \
  --file file.txt

Create an Append Blob

az storage blob create \
  --account-name mystorageaccount \
  --container-name logs \
  --name app.log \
  --type append

Create a Page Blob

az storage blob create \
  --account-name mystorageaccount \
  --container-name vhds \
  --name disk.vhd \
  --type page \
  --size 1073741824

The --type parameter explicitly defines whether the blob is created as a block, append, or page blob.

Summary

  • Block blobs provide scalable storage for large unstructured data.
  • Append blobs are optimized for append-only workloads like logging.
  • Page blobs provide disk-like storage with random read/write access.
  • The blob type must be specified during creation using APIs, SDKs, or CLI.

Choosing the correct blob type ensures optimal performance, scalability, and cost efficiency in Azure Storage solutions.