# Azurite V3: an emulator generated from the storage SDK's swagger

> Azurite is a Node-based clone of Azure Storage, and the reason V3 exists is stated plainly in the README: the storage APIs keep changing, hand-written JavaScript was inefficient and bug-prone, and JavaScript had no type validation. The V3 server is generated from a modified copy of the same swagger the current Azure Storage SDKs use, which is why a dated API version rather than a feature list is the contract to check.

**Azure/Azurite** — A lightweight server clone of Azure Storage that simulates most of the commands supported by it with minimal dependencies

- Repository: https://github.com/Azure/Azurite
- Stars: 2,267 · Forks: 394
- Language: TypeScript
- License: MIT
- Published: 2026-09-30 · Updated: 2026-09-30 · Language: en
- Canonical page: https://hysenlabs.com/projects/azure-azurite

## An API version is the contract: 2026-06-06

The single most decision-relevant number in this repository is a date.

The version table at the top of the README pairs each Azurite release with the Azure Storage API version it implements. Azurite 3.37.0 is listed against API version 2026-06-06, supporting Blob, Queue and Table with Table marked as preview. The legacy V2 line, which lives on a separate `legacy-master` branch, is listed against API version 2016-05-31 and the same three services without the preview marker.

That is the whole compatibility story in two rows, and it has two consequences. If your code calls an operation introduced after 2026-06-06, this emulator does not implement it, and the README directs you to the support matrix section to find out exactly what is covered rather than leaving you to guess. And V2 is frozen roughly a decade behind on API surface, so choosing between the branches is not a preference, it is a date comparison.

The feature lists that follow are written against those versions, which is the pattern to get used to. Blob support covers Shared Key, Account SAS, Service SAS, public access and OAuth authentication, get and set of blob service properties, container create, list and delete, full CRUD on block blobs and page blobs, and CRC-64 with NVME transactional checksum validation on Put Blob, Put Block, Append Block and Put Page. Queue support covers Shared Key, Account SAS, Service SAS and OAuth, get and set of queue service properties, preflight requests, queue create, list and delete, and put, get, peek, update, delete and clear on messages.

Table is the odd one out. Its alignment is stated against Azure Storage API version 20, which reads as an incomplete value rather than a date, and it is the one service the README labels preview. Treat Table as the least trustworthy part of the emulator.

## Why V3 exists: a generator fed by the storage swagger

The rationale for the rewrite is the best argument in this README, and it is worth quoting in substance.

Azurite V2 was manually written in pure JavaScript, and it was popular and active as an open source project. But Azure Storage APIs grow and keep updating, so keeping a hand-written emulator in step is inefficient and prone to bugs. And JavaScript lacks strong type validation, which the author identifies as the obstacle to easy collaboration. Both are maintenance arguments rather than performance ones.

V3 answers them with a TypeScript Server Code Generator written for the project, and the crucial detail is its input. The generator uses the same swagger, modified, that the new Azure Storage SDKs use. So the emulator's server surface and Microsoft's own client library are generated from one document, which is why the README can claim better code alignment with the storage APIs rather than merely a rewrite in a typed language.

That single design decision also explains the shape of the repository. There is a `swagger/` directory at the top level, which is the generator's input, and the generator itself lives alongside the generated code under `src/`. When you want to know whether the emulator will behave like the service, the swagger is the document to read, not the issue tracker.

One word in that paragraph deserves attention. The swagger is described as modified. A modification is where deliberate divergence lives, and it is the first place to look when Azurite and Azure Storage disagree about an edge case that the generator could not express faithfully.

For context on the migration, the first release on the new architecture was 3.0.0-preview, and the current one is 3.37.0.

## Four executables and three ports, so you can run one service

Azurite is not one binary. The package manifest ships four entry points, one for everything and one per service:

```json
"azurite": "./dist/src/azurite.js",
"azurite-blob": "./dist/src/blob/main.js",
"azurite-queue": "./dist/src/queue/main.js",
"azurite-table": "./dist/src/table/main.js"
```

Each service has its own default port, and the container image exposes all three: 10000 for blob, 10001 for queue and 10002 for table. So a test suite that only touches blobs can start the blob emulator alone and skip two listeners, two data directories and two background processes.

That is not just tidiness. Each service stores its own data, so running only what you use keeps the workspace small and stops one service's leftovers from confusing the next run. The README's command line documentation has separate sections for host, port and workspace path configuration, which is how you point a service-specific binary at a specific location.

The command line surface is where this becomes concrete, and the container image ships a ready-made example of the full set of options:

```dockerfile
CMD ["azurite", "-l", "/data", "--blobHost", "0.0.0.0", "--queueHost", "0.0.0.0", "--tableHost", "0.0.0.0"]
```

Read that line as documentation with a warning attached. It sets the workspace with `-l /data`, and it binds all three service hosts to `0.0.0.0` rather than to loopback, because a container that only listened on loopback would be unreachable from the host. The consequence is that anything you expose this image to can reach the emulator, so the port mapping is where the isolation has to happen.

## Five authentication schemes and a checksum that is validated

The authentication story is where an emulator most often differs from the service it clones, so it is worth being precise about what is covered.

For blob, the listed schemes are Shared Key, Account SAS, Service SAS, public access and OAuth. For queue it is Shared Key, Account SAS, Service SAS and OAuth. Public access appears only on the blob side, which matches the service's own split between a blob container that can be public and a queue that cannot. The README's table of contents also has dedicated sections for certificate configuration over HTTPS, in both PEM and PFX form, and for OAuth configuration.

The OAuth path is worth understanding because of what it implies about the implementation. The runtime dependencies include a JSON web token library, so bearer tokens are validated rather than accepted. An emulator that simply ignored the Authorization header would pass your tests and fail in production; one that validates the token will fail your tests earlier, which is the useful direction.

The other item on that list is the checksum work: CRC-64 and NVME transactional checksum validation for Put Blob, Put Block, Append Block and Put Page. This is the newest fidelity feature in the release notes and the one with the highest ratio of test value to implementation cost. Integrity validation is invisible when it works, and a mismatch in a production upload is a support ticket. Emulating it means your local tests exercise the failure path.

Two more dependencies explain the rest of the design. An embedded document store is the default metadata backend, while an ORM with MySQL and SQL Server drivers appears alongside a preview feature for keeping metadata in an external database, which is what you would use if your tests need to inspect state directly.

## The documented places Azurite is not Azure Storage

The README has a section titled the differences between Azurite and Azure Storage, and its subheadings are the honest scope statement of the project. They are storage accounts, endpoint and connection URL, scalability and performance, error handling, the API version compatible strategy, and RA-GRS.

Read that list as a set of questions to ask before you rely on the emulator. Storage accounts is about the identity model, and the way to configure custom account names and keys is one of the environment variable options in the README. Endpoint and connection URL is about what your application has to be told in order to reach a local endpoint rather than the real service. Error handling matters most for tests, because an emulator that returns a different status or error shape than the service will let a broken retry policy pass. Scalability and performance are the obvious limits of a single Node process. RA-GRS is listed on its own, which tells you that replication semantics are a known area of divergence rather than an afterthought.

The API version compatible strategy is the subtler one. An emulator has to decide what to do with a request carrying an API version it does not implement, and the existence of a documented strategy, together with a command line option to skip the API version check, implies that the default is to reject rather than guess. That is the behaviour you want in tests, and it is also the thing to switch off if you are chasing a version mismatch rather than a real incompatibility.

The table of contents also documents separate areas for loose mode configuration, access log configuration, debug log configuration, disabling product-style URLs and disabling telemetry collection. Those are the switches you reach for when an emulator test fails for a reason that has nothing to do with your code.

## A VS Code engine from 2018 on a Node 22 project

The container build is where the project's operational decisions are visible, and two of them are worth a close look.

The first is the runtime floor declared in the package manifest:

```json
"node": ">=22.0.0",
"vscode": "^1.39.0"
```

Those two lines belong to the same package, which is also published as a Visual Studio Code extension. The Node requirement is current; the VS Code requirement dates from 2018. A caret range from 1.39.0 accepts any later version, but it also means an editor older than that satisfies the constraint, and an editor that old will be asked to run a bundle built for Node 22. The mismatch is harmless for anyone on a current editor and confusing for anyone who reads the manifest, which is why it is worth naming rather than assuming it is intentional.

The second is the production image. It builds from an Alpine-based Node 22 image, sets `NODE_ENV` to production, declares a volume at `/data`, copies only the built `dist` directory from the builder stage, then installs production dependencies with dev dependencies omitted. Two details stand out. It neutralises a lifecycle script by setting `scripts.prepare` to a no-op before installing, which stops a post-install hook from running in an image with no toolchain. And after installing Azurite globally it removes npm, npx and the npm cache from the image, so there is no package manager left in a container whose only job is to run one process.

There is a second Dockerfile for Windows, and a README variant for the Microsoft Container Registry listing. Both exist because the project is distributed through several channels at once: npm, the Docker Hub image, the VS Code extension marketplace, and NuGet, which the table of contents covers alongside Visual Studio hosting, Testcontainers and Docker Compose examples.

## MIT, Table in preview, and releases that skip quarters

The licence is MIT, with a NOTICE file alongside it and a ChangeLog.md and a BreakingChanges.md at the top level, which is more upgrade hygiene than most emulator projects bother with. The last push was on 2026-09-28 and the repository is not archived.

The release history is worth reading for its shape rather than its content. Azurite 3.37.0 shipped on 2026-08-26, 3.36.0 on 2026-07-17, and 3.35.0 on 2025-08-01. That last date is more than a year before the previous two, which tells you the cadence is event-driven rather than scheduled: the emulator moves when the storage service moves, because its job is to track that API surface.

The release titles use a calendar-year and month form while the tags use semver, so a tag and its release name disagree about the year, with 3.36.0 titled 2026.07 and 3.35.0 titled 2025.07. If you are scripting against this repository, use the semver tag.

Two smaller items for anyone reading the tree. Both `eslint.config.js` and `tslint.json` are present, which is the residue of a linting migration rather than a deliberate dual configuration. And the dev dependencies include the actual Azure client libraries, the blob and queue packages plus the identity and data-tables packages, which is the strongest evidence available about testing quality: the emulator is exercised by the same SDKs your application uses.

Which leaves the one decision that matters. Pin the Azurite version, then check its support matrix against the operations your code calls, because that table rather than the README's feature list is what tells you whether a green local run means anything.

## Conclusion

Use Azurite V3 for local and continuous integration runs against blob and queue, and pin the emulator version to the one whose support matrix covers the operations your code calls, because alignment is asserted against a dated API version rather than a feature set. Do not rely on it for Table storage, which the README marks as preview, or for the behaviours the differences section covers, including scalability and RA-GRS. If you run the container, note that its default command binds the blob, queue and table hosts to 0.0.0.0, so restrict the port mapping instead of assuming a loopback default.

## FAQ

### Which version of the Azure Storage API does Azurite emulate?

Azurite 3.37.0 is listed against Azure Storage API version 2026-06-06 for blob and queue, with Table in preview. The legacy V2 branch is listed against 2016-05-31, so the two branches differ by about a decade of API surface.

### What is the difference between Azurite V2 and Azurite V3?

V2 was hand-written in pure JavaScript and is frozen on the legacy-master branch. V3 implements a new architecture where the server code is generated by a TypeScript Server Code Generator that consumes a modified copy of the same swagger the new Azure Storage SDKs use, which the project says reduces manual effort and improves alignment with the storage APIs.

### Can I run only the blob or only the queue part of Azurite?

Yes. The package ships four executables, azurite for everything plus azurite-blob, azurite-queue and azurite-table, and each service listens on its own port, 10000 for blob, 10001 for queue and 10002 for table. Host, port and workspace path are all configurable per invocation.

### Does Azurite support Azure Storage authentication and checksums?

Blob covers Shared Key, Account SAS, Service SAS, public access and OAuth, while queue covers Shared Key, Account SAS, Service SAS and OAuth, and JWT tokens are validated rather than ignored. The current release also validates CRC-64 and NVME transactional checksums on Put Blob, Put Block, Append Block and Put Page.

### Where does Azurite differ from real Azure Storage?

The README has a dedicated section listing the differences under storage accounts, endpoint and connection URL, scalability and performance, error handling, the API version compatible strategy, and RA-GRS. Table storage is separately marked as preview, and there is a command line option to skip the API version check when you are debugging a version mismatch.

### What are the requirements to run the Azurite container image?

The image builds on an Alpine-based Node 22 image and needs Node 22 or newer for the package itself. Its default command runs azurite with the workspace at /data and binds the blob, queue and table hosts to 0.0.0.0, so you should restrict the published ports rather than assume a loopback default.

## Sources

- [Azure/Azurite on GitHub](https://github.com/Azure/Azurite)
- [Issues](https://github.com/Azure/Azurite/issues)
- [License: MIT](https://github.com/Azure/Azurite/blob/main/LICENSE)
- [README](https://github.com/Azure/Azurite/blob/main/README.md)
- [Releases](https://github.com/Azure/Azurite/releases)

---

Hysen Labs editorial analysis, written from the project's own repository and release notes. Cite the canonical page: https://hysenlabs.com/projects/azure-azurite
