You signed in with another tab or window. Reload to refresh your session.You signed out in another tab or window. Reload to refresh your session.You switched accounts on another tab or window. Reload to refresh your session.Dismiss alert
Adds Azure Blob Storage versioning support to Azurite, enabling applications to create, list, retrieve, and delete previous blob versions during local development.
This work introduces the account model abstraction designed in collaboration with the Azurite team. The account model provides a central place for account-scoped feature configuration so additional Azure Storage capabilities can be added without coupling them directly to server startup or individual blob handlers.
Blob versioning is currently the first and only feature backed by this abstraction. The design supports Azurite's multi-account mode, allowing each configured account to enable or disable versioning independently. Accounts without an explicit versioning setting retain the existing non-versioned behavior for backward compatibility.
Motivation
Blob versioning automatically preserves previous blob states after modification or deletion. Without emulator support, applications that depend on version-aware workflows cannot be tested locally before deployment to Azure.
Implementation
Adds an account-level AccountModel setting for enabling blob versioning.
Supports file-based and inline JSON account configuration, including multiple accounts.
Persists account configuration in Loki metadata storage.
Creates version IDs as ISO 8601 timestamps when version-producing blob operations occur.
Supports retrieving and deleting a specific version through versionId.
Supports listing versions through includeVersions with version-aware continuation markers.
Preserves previous versions as immutable records while tracking the current version.
Adds versioning behavior across block, append, and page blob operations.
Adds VS Code extension settings for account configuration.
Preserves backward compatibility by defaulting accounts without versioning configuration to versioning disabled.
Configuration
Blob versioning can be configured using:
--accountConfigFilePath for JSON configuration files.
--accountConfigAsJson for inline JSON configuration.
Configured accounts must also be present in AZURITE_ACCOUNTS for authentication.
Behavior
Block blob writes create versions except for Put Block.
Page and append blobs create versions for Put Blob, Put Block List, Set Blob Metadata, and Copy Blob.
Put Page and Append Block do not create versions.
Previous versions can be read or deleted using their version ID.
Version IDs use ISO 8601 timestamps with seven fractional-second digits. JavaScript supplies the millisecond timestamp, and the final four digits distinguish versions created within the same millisecond.
Limitations
This change does not currently support:
Soft-delete integration
Blob expiration with versioning
SAS URIs targeting specific versions
Version-level immutability policies
Validation
TypeScript build and lint pass.
Blob version pagination tests pass.
Startup and persisted-data upgrade regression tests pass with versioning disabled.
The reason will be displayed to describe this comment to others. Learn more.
🔵 Needs a closer look
Unresolved correctness and compatibility issues remain in server construction, SQL persistence, version handling, pagination, configuration, and VS Code logging.
For a legacy continuation token, decodeBlobListMarker returns recordId = -1, so this SQL predicate admits every row with the same blob name (blobId > -1) instead of preserving the old name-exclusive marker semantics. A resumed internal listing can reprocess same-name records; handle legacy markers with only blobName > markerName before constructing the tuple predicate.
The parser claims each account configuration must be a JSON object, but arrays pass this check because typeof [] === "object"; an input such as account1:[{"isBlobVersioningEnabled":true}] is silently accepted and defaults versioning to false. Reject arrays explicitly so malformed configuration cannot disable the requested feature without an error.
The inMemory mode is not honored while opening the account store: an existing database file is still loaded unconditionally. If Azurite is restarted with --inMemoryPersistence after a persistent run, old account settings (including enabling versioning) are resurrected instead of starting empty. Skip the stat/load path when this.inMemory is true.
Legacy continuation tokens from the previous listAllBlobs implementation were plain blob names and meant that every record with that name had already been returned. Decoding such a token gives recordId = -1, so this predicate now re-emits every same-name record ($loki > -1) instead of skipping that name; this can make the GC iterator process old records again after an upgrade. Branch on isLegacyBlobListMarker(decodedMarker) and use only obj.name > markerName for legacy tokens.
The reason will be displayed to describe this comment to others. Learn more.
🔵 Needs a closer look
Unresolved issues remain in nullable VS Code schemas, SQL version-copy handling, version responses, uncommitted-record retention, and legacy pagination markers.
When a versioned account overwrites an uncommitted blob created by Put Block, this branch promotes that uncommitted record into a previous version and leaves it in the blob collection. Uncommitted records are not valid blob versions and can retain stale metadata/blocks for GC and later listings. Only preserve the existing record when isCommitted !== false; otherwise remove it as the pre-existing non-versioned behavior does.
🧠 Review effort: Lite
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Add this suggestion to a batch that can be applied as a single commit.This suggestion is invalid because no changes were made to the code.Suggestions cannot be applied while the pull request is closed.Suggestions cannot be applied while viewing a subset of changes.Only one suggestion per line can be applied in a batch.Add this suggestion to a batch that can be applied as a single commit.Applying suggestions on deleted lines is not supported.You must change the existing code in this line in order to create a valid suggestion.Outdated suggestions cannot be applied.This suggestion has been applied or marked resolved.Suggestions cannot be applied from pending reviews.Suggestions cannot be applied on multi-line comments.Suggestions cannot be applied while the pull request is queued to merge.Suggestion cannot be applied right now. Please check back later.
Title: Add Blob Versioning Support to Azurite
Summary
Adds Azure Blob Storage versioning support to Azurite, enabling applications to create, list, retrieve, and delete previous blob versions during local development.
Closes #665.
Account model
This work introduces the account model abstraction designed in collaboration with the Azurite team. The account model provides a central place for account-scoped feature configuration so additional Azure Storage capabilities can be added without coupling them directly to server startup or individual blob handlers.
Blob versioning is currently the first and only feature backed by this abstraction. The design supports Azurite's multi-account mode, allowing each configured account to enable or disable versioning independently. Accounts without an explicit versioning setting retain the existing non-versioned behavior for backward compatibility.
Motivation
Blob versioning automatically preserves previous blob states after modification or deletion. Without emulator support, applications that depend on version-aware workflows cannot be tested locally before deployment to Azure.
Implementation
AccountModelsetting for enabling blob versioning.versionId.includeVersionswith version-aware continuation markers.Configuration
Blob versioning can be configured using:
--accountConfigFilePathfor JSON configuration files.--accountConfigAsJsonfor inline JSON configuration.Configured accounts must also be present in
AZURITE_ACCOUNTSfor authentication.Behavior
Limitations
This change does not currently support:
Validation