This chapter covers local Azure development using Azurite and other emulators, a critical skill for AZ-204 candidates who must write and test Azure Storage code without incurring cloud costs. The exam expects you to know how to configure Azurite, connect to it from your code, and understand its limitations versus the real Azure service. Approximately 5-10% of exam questions touch on local development tools, including Azurite, Storage Emulator, and Cosmos DB Emulator. Mastering this chapter ensures you can answer questions about connection strings, default ports, and when to use an emulator versus the cloud service.
Jump to a section
Think of Azurite as a high-fidelity flight simulator for Azure Storage. Just as a pilot practices takeoffs and landings in a simulator before flying a real plane, a developer uses Azurite to test blob, queue, and table storage operations locally before deploying to Azure. The simulator mimics the cockpit instruments, controls, and physics accurately enough that the pilot's actions transfer directly to the real aircraft. Similarly, Azurite emulates the Azure Storage REST APIs, including authentication, error codes, and performance characteristics, so your code can run unchanged against both the emulator and the actual cloud service. However, the simulator does not replicate the full experience of air traffic control, weather, or other planes—just as Azurite does not replicate the full scale, latency, or global replication of Azure Storage. It is a tool for development and unit testing, not for load testing or production validation. When you connect to Azurite using the well-known connection string 'UseDevelopmentStorage=true', your SDK automatically redirects requests to localhost on the default ports (10000 for blob, 10001 for queue, 10002 for table). The SDK's retry policies, timeouts, and authentication mechanisms all work as they would against the real service, but the emulator always returns success quickly, so you must be aware that network failures and throttling are not simulated. This allows you to iterate rapidly without incurring costs or waiting for cloud provisioning.
What is Azurite and Why It Exists
Azurite is an open-source, cross-platform emulator for Azure Blob, Queue, and Table storage. It replaces the legacy Azure Storage Emulator (which only ran on Windows and had limited features). Azurite runs on Windows, macOS, and Linux, and supports all three storage services in a single process. The primary purpose is to allow developers to write and test code against a local endpoint that mimics the Azure Storage REST APIs, without needing an active Azure subscription or internet connectivity. This accelerates development, reduces costs, and enables offline testing.
How Azurite Works Internally
Azurite implements the Azure Storage REST API protocol by listening on HTTP/HTTPS ports (default 10000 for blob, 10001 for queue, 10002 for table). When your application sends a request (e.g., PUT to create a blob), Azurite parses the request, validates authentication (shared key or SAS token), and performs the operation on the local file system. Data is stored in a configurable directory (default: %USERPROFILE%\.azurite on Windows, ~/.azurite on Linux/macOS). Azurite supports both in-memory and persistent storage modes. In persistent mode, data survives restarts; in-memory mode is for testing where state should not persist. Azurite also supports OAuth authentication via a local token endpoint, but for simplicity, most developers use the well-known connection string UseDevelopmentStorage=true which uses a fixed account name and key (Eby8vdM02xNOcqFlqUwJPLlmEtlCDXJ1OUzFT50uSRZ6IFsuFq2UVErCz4I6tq/K1SZFPTOtr/KBHBeksoGMGw==). This key is publicly known and must never be used in production.
Key Components, Values, Defaults, and Timers
Default Ports: Blob: 10000, Queue: 10001, Table: 10002. These can be overridden with command-line flags (e.g., --blobPort 10010).
Default Connection String: DefaultEndpointsProtocol=http;AccountName=devstoreaccount1;AccountKey=Eby8vdM02xNOcqFlqUwJPLlmEtlCDXJ1OUzFT50uSRZ6IFsuFq2UVErCz4I6tq/K1SZFPTOtr/KBHBeksoGMGw==;BlobEndpoint=http://127.0.0.1:10000/devstoreaccount1;QueueEndpoint=http://127.0.0.1:10001/devstoreaccount1;TableEndpoint=http://127.0.0.1:10002/devstoreaccount1;
Well-Known Connection String: UseDevelopmentStorage=true (automatically resolves to the above).
Account Name: devstoreaccount1 (fixed).
Storage Location: Default ~/.azurite or %USERPROFILE%\.azurite. Configurable via --location flag.
Silent Mode: Azurite can run in silent mode (--silent) to suppress logs.
OAuth Endpoint: Azurite provides a local OAuth endpoint at http://localhost:10000/oauth for testing with Azure AD tokens.
CORS: Azurite supports CORS configuration via command-line arguments or by setting CORS rules programmatically.
Performance: Azurite is single-threaded by default, but can handle moderate loads. It is not designed for load testing.
Configuration and Verification Commands
To install Azurite globally via npm:
npm install -g azuriteTo start Azurite with default settings:
azuriteTo start with custom ports and location:
azurite --blobPort 10010 --queuePort 10011 --tablePort 10012 --location C:\MyStorage --debugTo verify Azurite is running, use a tool like curl or Azure Storage Explorer:
curl http://127.0.0.1:10000/devstoreaccount1?comp=listThis should return an XML listing of containers (empty initially).
How Azurite Interacts with Related Technologies
Azurite works seamlessly with the Azure Storage SDKs (for .NET, Java, Python, Node.js, etc.). When you set the connection string to UseDevelopmentStorage=true in your app configuration, the SDK automatically resolves the endpoint to localhost. Azurite also integrates with Azure Functions local runtime, enabling local testing of blob/queue/table triggers. For Cosmos DB, a separate emulator exists (Cosmos DB Emulator) which runs on port 8081. Azurite does not emulate Cosmos DB. For Table storage, note that Azurite emulates the old Azure Table Storage API, not the newer Cosmos DB Table API. If your app targets Cosmos DB Table API, use the Cosmos DB Emulator instead.
Limitations of Azurite
No Geo-Replication: Azurite does not simulate RA-GRS or LRS replication.
No Scale: Throughput is limited to a single process.
No Network Latency: Operations complete instantly, so you cannot test timeouts or retries due to network issues.
No Throttling: Azurite does not enforce storage account limits (e.g., 20,000 IOPS per account).
No Soft Delete: Soft delete for blobs is not supported.
No Static Websites: The static website feature of Azure Storage is not emulated.
No File Shares: Azurite does not support Azure Files.
No Encryption at Rest: Data is stored as plain files.
Despite these limitations, Azurite is the recommended local development tool for Azure Storage.
Install Azurite via npm
Open a terminal and run `npm install -g azurite`. This installs the Azurite package globally. Ensure Node.js (v10 or later) is installed. On Windows, you may also use Chocolatey (`choco install azurite`). After installation, verify with `azurite --version`. The command installs the Azurite executable and its dependencies. No other prerequisites are needed.
Configure storage location and ports
Decide where Azurite will store data and which ports to use. By default, data goes to `~/.azurite` and ports 10000-10002. For persistent storage, ensure the location directory exists. You can override with `--location` and `--blobPort`, `--queuePort`, `--tablePort`. Example: `azurite --location D:\AzuriteData --blobPort 10010`. This is useful if you want to keep data in a specific project folder or avoid port conflicts.
Start Azurite in persistent mode
Run `azurite` in the terminal. By default, Azurite runs in persistent mode (data saved to disk). To use in-memory mode (data lost on stop), add `--inMemoryPersistence`. The console will log the endpoints: `Azurite Blob service is starting at http://127.0.0.1:10000` etc. Keep the terminal open while developing. Azurite runs as a foreground process; you can run it in the background using `azurite &` on Linux/macOS.
Configure application connection string
In your application code or configuration file (e.g., appsettings.json for .NET), set the storage connection string to `UseDevelopmentStorage=true`. This is the simplest method. Alternatively, use the full connection string: `DefaultEndpointsProtocol=http;AccountName=devstoreaccount1;AccountKey=Eby8vdM02xNOcqFlqUwJPLlmEtlCDXJ1OUzFT50uSRZ6IFsuFq2UVErCz4I6tq/K1SZFPTOtr/KBHBeksoGMGw==;BlobEndpoint=http://127.0.0.1:10000/devstoreaccount1;QueueEndpoint=http://127.0.0.1:10001/devstoreaccount1;TableEndpoint=http://127.0.0.1:10002/devstoreaccount1;`. The SDK will automatically use these endpoints.
Run and test application locally
Start your application. All storage operations (create container, upload blob, send queue message, query table) will be executed against Azurite. Use Azure Storage Explorer to view the data visually. You can also use curl or Postman to send REST requests. Verify that operations succeed and data persists after restart if using persistent mode. If you encounter errors, check Azurite console logs for details.
Enterprise Scenario 1: Offline Development for a Healthcare Application
A healthcare startup is building a patient records system using Azure Blob Storage for medical images. Developers work remotely, often with limited internet. They use Azurite to run the entire storage layer locally. Each developer has Azurite running on their machine with persistent storage in a project folder. They configure their ASP.NET Core app to use UseDevelopmentStorage=true in appsettings.Development.json. This allows them to write and test blob uploads, downloads, and metadata operations without any cloud connectivity. The team uses Azure Storage Explorer connected to the local endpoint to verify data. The main challenge is that Azurite does not enforce blob size limits, so a developer might upload a 5TB file locally that would fail in production. They mitigate this by adding a validation layer that checks blob size before upload. Also, since Azurite does not simulate network failures, they must manually test retry logic by stopping Azurite temporarily. Performance is not an issue because each developer works with small datasets.
Scenario 2: CI/CD Pipeline with Azurite in Docker
A financial services company uses Azure DevOps for CI/CD. Their integration tests require Azure Storage. They run Azurite in a Docker container as part of the pipeline. The Docker image mcr.microsoft.com/azure-storage/azurite is used. The pipeline starts Azurite, runs tests, and then stops the container. The connection string is set to UseDevelopmentStorage=true but because the container runs on a different host, they use the full connection string with the container's IP address. They also use the --silent flag to reduce log noise. The tests cover blob, queue, and table operations. One issue they faced is that Azurite does not support shared access signatures (SAS) with stored access policies; they had to modify tests to use simple SAS tokens. Also, Azurite does not support blob lease duration beyond 60 seconds, so lease-related tests had to be adjusted. This approach saved costs by avoiding provisioning an actual storage account for every build.
Scenario 3: Cosmos DB Emulator for Table API
A retail company uses Cosmos DB Table API for order processing. They need local development. They use the Cosmos DB Emulator (not Azurite) because Azurite only emulates the old Azure Table Storage API, which lacks features like global distribution and consistency levels. The Cosmos DB Emulator runs on port 8081 and provides a similar experience. They configure the connection string to point to localhost:8081 with the emulator's account key. The emulator supports most Cosmos DB features, including stored procedures, triggers, and UDFs. However, it has limitations: it runs on a single partition, so throughput is limited to 10,000 RU/s. They use it for unit tests and integration tests. The main pitfall is that the emulator does not enforce request unit (RU) consumption exactly like the cloud, so they must load test against the real service before production deployment.
What AZ-204 Tests on This Topic
AZ-204 objective 1.1 (Compute) includes 'Develop Azure compute solutions' but also touches on storage emulation under 'Develop for Azure Storage' (objective 3.1). Specifically, the exam expects you to know:
The purpose and limitations of Azurite vs. real Azure Storage.
How to configure connection strings for local development (UseDevelopmentStorage=true).
Default ports and account names.
When to use Azurite vs. Cosmos DB Emulator.
The fact that Azurite does NOT support Azure Files, static websites, or geo-replication.
Common Wrong Answers and Why Candidates Choose Them
'Azurite supports all Azure Storage features.' This is false. Candidates assume the emulator is complete. The exam tests limitations: no file shares, no static websites, no geo-replication, no soft delete.
'You must create a storage account in Azure before using Azurite.' Wrong. Azurite is fully local. Candidates confuse the need for an actual account in production with local emulation.
'Azurite uses port 10000 for all services.' No, each service has its own port. The exam may ask which port corresponds to blob/queue/table.
'UseDevelopmentStorage=true requires a real Azure subscription.' No, it automatically points to localhost. Candidates think it's a cloud-only setting.
'Azurite can be used for load testing.' False. It is single-threaded and not designed for scale. The exam might present a scenario where a team uses Azurite for performance testing and ask why results are misleading.
Specific Numbers and Terms That Appear on the Exam
Default ports: Blob=10000, Queue=10001, Table=10002.
Account name: devstoreaccount1.
Well-known connection string: UseDevelopmentStorage=true.
The emulator's primary key: Eby8vdM02xNOcqFlqUwJPLlmEtlCDXJ1OUzFT50uSRZ6IFsuFq2UVErCz4I6tq/K1SZFPTOtr/KBHBeksoGMGw==.
Azurite is cross-platform; Storage Emulator is Windows-only.
Cosmos DB Emulator uses port 8081.
Edge Cases and Exceptions
If you change the default ports, the well-known connection string no longer works; you must use the full connection string.
Azurite does not support HTTPS by default; you must provide a certificate to enable HTTPS.
When using OAuth with Azurite, the emulator provides a local token endpoint, but the token is not valid for Azure; it's only for local testing.
Azurite does not support the x-ms-version header for all API versions; it supports up to a certain version (check documentation).
How to Eliminate Wrong Answers
For any question about Azurite, ask yourself: 'Would this feature require cloud infrastructure?' If yes (e.g., geo-replication, global scale, static website), Azurite does not support it. Also, remember that Azurite is for development and unit testing, not for performance or integration testing that depends on cloud behavior. If a question asks about a feature that is explicitly listed as unsupported (like Azure Files), eliminate that answer. For connection string questions, look for 'UseDevelopmentStorage=true' or the full string with localhost endpoints.
Azurite is the recommended local emulator for Azure Blob, Queue, and Table storage; it is cross-platform and open source.
Default ports: Blob=10000, Queue=10001, Table=10002; account name: devstoreaccount1.
Use connection string 'UseDevelopmentStorage=true' or the full string with localhost endpoints for local development.
Azurite does NOT support Azure Files, static websites, geo-replication, soft delete, or encryption at rest.
Azurite is for development and unit testing only; not for load or performance testing.
Cosmos DB Emulator (port 8081) is used for Cosmos DB Table API, not Azurite.
The legacy Azure Storage Emulator is Windows-only and deprecated; use Azurite instead.
These come up on the exam all the time. Here's how to tell them apart.
Azurite
Cross-platform (Windows, macOS, Linux)
Supports Blob, Queue, and Table (single process)
Open source and actively maintained
Can run in Docker containers
Supports both persistent and in-memory modes
Azure Storage Emulator (Legacy)
Windows only
Supports Blob, Queue, and Table (separate processes)
Deprecated and no longer updated
Cannot run in Docker (Windows-only)
Persistent mode only
Mistake
Azurite supports all Azure Storage services including Azure Files.
Correct
Azurite only emulates Blob, Queue, and Table storage. Azure Files is not supported. For File shares, you must use the real service or a third-party emulator.
Mistake
Azurite can be used for production-like load testing.
Correct
Azurite is single-threaded and runs on a single machine. It does not simulate network latency, throttling, or scale. Load testing against Azurite gives misleading results.
Mistake
UseDevelopmentStorage=true requires an active Azure subscription.
Correct
UseDevelopmentStorage=true is a well-known connection string that resolves to localhost endpoints. It does not require any Azure subscription or internet connectivity.
Mistake
Azurite uses the same ports for all storage services.
Correct
Each service uses a distinct port: blob on 10000, queue on 10001, table on 10002. They can be changed individually.
Mistake
Azurite supports OAuth tokens that can be used in production.
Correct
Azurite provides a local OAuth endpoint for testing, but the tokens are not valid for Azure. They are only for local emulation. Production code must use Azure AD tokens.
Reveal each answer, then mark whether you got it right. Score 60%+ to unlock the next chapter.
Azurite is the modern, cross-platform emulator that replaces the legacy Azure Storage Emulator (Windows-only). Azurite supports Blob, Queue, and Table in a single process, runs on macOS and Linux, and is open source. The legacy emulator is deprecated and no longer updated. For AZ-204, always choose Azurite unless the question explicitly mentions Windows-only legacy.
Set the connection string to 'UseDevelopmentStorage=true' in your app configuration (e.g., appsettings.json). This automatically points to localhost:10000-10002 with the default account. Alternatively, use the full connection string with explicit endpoints. The SDK will handle the rest.
Yes, Azurite is often used in CI/CD pipelines, typically as a Docker container. Use the official image 'mcr.microsoft.com/azure-storage/azurite'. However, remember that Azurite does not simulate cloud-specific behaviors like throttling or latency, so tests may pass locally but fail in production due to those factors.
By default, Azurite uses HTTP. To enable HTTPS, you must provide a PFX certificate file using the --cert and --key options. For development, self-signed certificates are acceptable but browsers will show warnings. The exam expects you to know that HTTPS is not default.
Key limitations: no Azure Files, no static websites, no geo-replication, no soft delete, no encryption at rest, no throttling, no network latency simulation, and it is single-threaded. Also, it does not support stored access policies for SAS tokens. These limitations are commonly tested on the exam.
Use the --blobPort, --queuePort, and --tablePort flags when starting Azurite. For example: 'azurite --blobPort 10010 --queuePort 10011 --tablePort 10012'. If you change ports, you must update your connection string accordingly; 'UseDevelopmentStorage=true' will no longer work.
No, Azurite emulates the old Azure Table Storage API, not the Cosmos DB Table API. For Cosmos DB Table API, use the Cosmos DB Emulator (port 8081). The exam distinguishes between these two.
You've just covered Local Azure Development with Azurite and Emulators — now see how well it sticks with free AZ-204 practice questions. Full explanations included, no account needed.
Done with this chapter?