Library / SDK
Azure/azure-sdk-for-js avatar
Azure/azure-sdk-for-js

azure-sdk-for-js: two package families and one migration hazard

This repository is for active development of the Azure SDK for JavaScript (NodeJS & Browser). For consumers of the SDK we recommend visiting our public developer docs at https://docs.microsoft.com/javascript/azure/ or our versioned developer docs at https://azure.github.io/azure-sdk-for-js.

2,296 stars1,400 forksTypeScriptMIT

At a glance

What is it?
The Azure SDK for JavaScript is a pnpm monorepo where two kinds of package live side by side: client libraries that follow the TypeScript design guidelines and share retries, logging and identity, and @azure/arm- management libraries generated from service swagger. That split is easy to spot in a package name and easy to trip over during an upgrade.
Who is it for?
Use azure-sdk-for-js for anything that benefits from generated types and a shared HTTP pipeline, and check the releases page before installing to see whether the specific package follows the current design guidelines. Do not upgrade management packages without reading documentation/MIGRATION-guide-for-next-generation-management-libraries.md, because the authentication code changes with the version.
Can I use it commercially?
Yes. MIT is a permissive licence: you can use, modify and sell software built on it, as long as you keep its copyright and licence notices.
Is it still maintained?
Yes. The repository last received commits 2 days ago.
What is it written in?
Mainly TypeScript, according to GitHub's language statistics.

Answers come from the project's GitHub data, last synced on September 28, 2026, and from our analysis. They are not legal advice.

Editorial analysis

Two package families, and the naming rule that tells them apart

Everything you need to know about this repository is in one naming convention. Management libraries carry `@azure/arm-` in their package name; client libraries do not. Management packages provision and manage Azure resources through Azure Resource Manager. Client packages consume a resource that already exists and interact with it.

The two families are built very differently, and the difference explains most of the trade-offs you will meet.

Client libraries are hand-shaped around the design guidelines for JavaScript and TypeScript, and most of them share core functionality across the board: retries, logging, transport protocols and authentication protocols. The README says plainly that others have not been converted yet and will be updated in the near future, and that the releases page carries the list of which ones already follow the current guidelines. That list is the thing to check, because it tells you whether a specific package gives you the shared core or a one-off implementation.

Management libraries are, in the README's word, purely auto-generated based on the swagger files that represent the resource management APIs. The newer generation of them follows the same design guidelines and therefore shares capabilities across every Azure SDK: the Azure Identity library, an HTTP pipeline with custom policies, error handling and distributed tracing.

The repository is the active development home for both, and the consumer-facing documentation is elsewhere, at the public developer docs for current API references and the versioned developer docs for older ones. That split is deliberate and it is the first thing to internalise before upgrading anything.

Generated from swagger, so the types cannot drift

The generation model is the interesting engineering decision here, and it is worth understanding what you get from it.

A management library is produced from the swagger definition of the service's resource management API. That means the TypeScript surface is derived from the same document the service is built from. A property that does not exist cannot appear in your types, and a property that exists cannot be missing. For code that provisions infrastructure, that is a stronger guarantee than a handwritten client ever offers, because the compiler is reading the service contract rather than somebody's memory of it.

The alternative is to call the ARM REST API yourself with fetch. You lose a dependency and gain total control over the wire, but you also take on everything the generated package would have given you: retry behaviour, the HTTP pipeline and its custom policies, identity integration, consistent error types, distributed tracing hooks and paging. The README lists those as the shared core, and for most teams that list is the reason to take the package rather than write the request.

The cost of generation is equally real. A generated surface has the shape of the service, including the parts you did not want: deeply nested resource graphs, operation names that mirror REST paths, and property bags where the API models a dictionary of arbitrary settings. Client libraries, being hand-shaped, tend to be friendlier for consumption. That is why the repository contains both.

The generation config lives in the repository as `swagger_to_sdk_config.json`, so the pipeline is inspectable rather than magical.

The authentication break that comes with an upgrade

There is one hazard in this repository that deserves its own warning, and the README calls it out directly.

If you are experiencing authentication issues with the management libraries after upgrading certain packages, it is likely that you upgraded to the new versions without changing your authentication code. The fix is in the migration guide, at `documentation/MIGRATION-guide-for-next-generation-management-libraries.md`.

So the older and newer management libraries are not drop-in replacements. The newer ones route credentials through the Azure Identity library, which is the right model, but it means the credential object you construct and pass changes shape. An upgrade that only bumps versions in your lockfile produces an error at runtime rather than at build time, which is the worst possible moment to discover it.

The second warning is shorter and easier to check. Some packages have beta versions, and if you need to be sure your code is production-ready you should use a stable, non-beta package. The version number alone will not tell you, and the release names in this repository show why: `@azure/provisioning-keyvault_1.0.0-beta.1` and `@azure/provisioning-core_1.0.0-beta.1` were both cut on the same day, while `@azure/storage-queue_12.32.0` came from the mature line. A 1.0.0 can be a beta and a 12.32.0 can be years of production use.

The practical sequence is: check the beta suffix, check whether the package is on the new guidelines list, then read the migration guide before you upgrade rather than after.

Turning off telemetry means deleting the User-Agent header

This is the most unusual piece of configuration in the repository, and it is worth reading twice.

Telemetry collection is on by default. The documented opt-out is not an environment variable and not a settings file. You disable it at client construction, by creating a custom HTTP pipeline policy that removes the user agent string and passing that policy into the `additionalPolicies` option. That disables telemetry for all methods on that client, and the instruction that follows is that you must do it for every new client you create.

The policy itself is small. The header deletion is the whole mechanism:

javascript
import { SecretClient } from "@azure/keyvault-secrets";
import { ManagedIdentityCredential } from "@azure/identity";

function removeUserAgentPolicy() {
  return {
    name: "removeUserAgentPolicy",
    sendRequest(request, next) {
      request.headers.delete("User-Agent");
      return next(request);
    },
  };
}

The policy is then attached per call when the client is built:

javascript
  const secretClient = new SecretClient(keyvaultUri, credential, {
    additionalPolicies: [
      {
        position: "perCall",
        policy: removeUserAgentPolicy(),
      },
    ],
  });

Read this as an architectural comment rather than a snippet. Telemetry in these libraries is carried in a transport header, which means the opt-out lives in the HTTP pipeline and therefore requires understanding the pipeline at all. The stated instruction to repeat it for every new client is a maintenance obligation, and the natural way to discharge it is a small factory function of your own that every piece of code goes through. The example in the README wraps exactly that logic in a `createSecretClientWithManagedIdentity` function, which is the shape to copy.

The broader policy is documented on the Telemetry Guidelines page rather than in the README, and the README also points at Microsoft's privacy statement.

turbo, pnpm 11.24.0 and one build target per runtime

The build system is described by its filenames, and there are more of them than you would expect from a JavaScript project.

The root package is `@azure/monorepo`, marked private, version 0.0.1, and every task is a turbo task fanned out across the workspace:

json
"preinstall": "npx only-allow pnpm",
"build": "turbo build",
"test:browser": "turbo run test:browser",
"test:esm": "turbo run test:esm"

The `preinstall` hook is worth pausing on: `only-allow pnpm` means the monorepo refuses an install under npm or yarn rather than documenting that you should not use one. `[email protected]` is declared as the package manager and `node >=22.13` as the engine requirement, both exact enough to fail fast on a contributor machine.

Then the TypeScript configuration split. The tree holds separate `tsconfig` files for the source in CommonJS, in ESM, in a browser, for build output, for React Native and for workerd. The last two are the interesting ones: workerd is the Cloudflare Workers runtime, so a package here can be compiled for a serverless edge runtime as well as a browser, and React Native is a separate target from React for the DOM. Test targets match, with `test:node`, `test:browser` and `test:esm`, and Vitest configured through several base and shared config files plus a workspace file.

Two smaller signals about how seriously the publishing is taken. `@arethetypeswrong/cli` is a dev dependency, which is the tool that checks whether the type declarations a package publishes actually resolve correctly under different module resolution settings. And `api-extractor-base.json` with `tsdoc.json` is the API report machinery, which is how you detect an unintended breaking change in a public surface before you publish it.

There is also a `purge` script that clears `sdk/**/node_modules/` with rimraf, which is the kind of task that exists because a pnpm workspace at this size accumulates state that a normal install will not fix.

Browser and edge are targets, not claims

The description says Node.js and Browser, and the repository backs that up with build outputs and samples rather than a sentence of marketing.

Under `samples/` there are five directories: Bundling, cors, frameworks, web-workers and a README. Each names a problem that only appears once your code runs in a browser rather than on a server. Cross-origin requests are the obvious one, since a browser will refuse them unless the response says otherwise. Web workers change the threading model. Bundling changes how the package is resolved by a bundler rather than by Node's loader. Frameworks is the general case.

The React Native and workerd TypeScript targets above extend the claim past the browser to a mobile runtime and an edge runtime, which is a rare combination in a cloud SDK and tells you something about how the packages are structured underneath.

For anyone reading this to decide whether the SDK is usable in a browser, the practical checks are these five sample directories, the browser-specific `tsconfig`, and the browser test target. If your framework is not in that list, the `frameworks` sample is the one to read first.

One asymmetry is worth noting. The browser story is about how the packages are built and resolved. Capture and consumption of the telemetry header still happens at the transport layer in every environment, which is why the opt-out in the previous section applies to a browser client exactly as it does to a server one.

Which documentation you read depends on which version you installed

Documentation is split by version, and picking the wrong one is the most common wasted afternoon when working with this SDK.

For the latest versions, API reference documentation lives on the public developer docs. For older versions, it lives in the versioned developer docs hosted from this repository. The README's guidance is therefore: use the current docs unless you are pinned to an older package, in which case the versioned site is the correct reference.

The per-package README is the third layer, and it is the one you will actually read while writing code. It contains the code samples and the package information, it lives in the package folder under the service folder inside the `/sdk` directory of the repository, and the same file appears on the package's npm landing page. That last detail is the useful one: the documentation you get from npm is the documentation from this repository, so there is no second version to drift.

Two more references belong on the same list. The releases page lists which management libraries follow the current guidelines and which client libraries do, which turns the design-system question into a lookup. And `SUPPORT.md` in the repository root covers support, with GitHub Issues and a StackOverflow tag `azure-sdk-js` as the two public channels.

For the design rules themselves, the guidelines for JavaScript and TypeScript are published separately, and the in-repository `design/` and `documentation/` directories are where proposals and guides live. `CONTRIBUTING.md`, `AGENTS.md`, `SECURITY.md` and a `.mcp.json` at the root complete the picture of a repository that expects contributions from both people and tooling.

Editorial conclusion

Use azure-sdk-for-js for anything that benefits from generated types and a shared HTTP pipeline, and check the releases page before installing to see whether the specific package follows the current design guidelines. Do not upgrade management packages without reading documentation/MIGRATION-guide-for-next-generation-management-libraries.md, because the authentication code changes with the version. Verify the beta suffix rather than the version number, since provisioning packages ship as 1.0.0-beta.1 while mature ones sit at 12.x, and remember the telemetry opt-out applies per client construction.

Frequently asked questions

What is the difference between client and management packages in the Azure SDK for JavaScript?

Management libraries provision and manage Azure resources through Azure Resource Manager and are recognisable by `@azure/arm-` in their package name; they are purely auto-generated from the swagger files that describe the management APIs. Client libraries consume a resource that already exists, follow the Azure SDK design guidelines for JavaScript and TypeScript, and share core functionality such as retries, logging, transport protocols and authentication protocols.

How do I turn off telemetry in the Azure SDK for JavaScript?

Telemetry is on by default and the documented opt-out happens at client construction: create an HTTP pipeline policy that deletes the User-Agent header and pass it in through the `additionalPolicies` option with `position: "perCall"`. The README states you must do this for every new client, so a shared factory function is the practical way to apply it.

Why does authentication break when I upgrade Azure management packages?

The newer generation of management libraries routes credentials through the Azure Identity library, so upgrading without changing the authentication code leaves the credential object mismatched. The README points at documentation/MIGRATION-guide-for-next-generation-management-libraries.md for the transition, and the failure appears at runtime rather than at build time.

Are all azure-sdk-for-js packages production ready?

No, and the version number does not tell you. The README says some packages have beta versions and that you should use a stable, non-beta package for production code. Recent releases include `@azure/provisioning-keyvault_1.0.0-beta.1` and `@azure/provisioning-core_1.0.0-beta.1` alongside `@azure/storage-queue_12.32.0`, so a 1.0.0 can be a beta while a 12.x line is mature.

Does the Azure SDK for JavaScript work in browsers and edge runtimes?

Yes, and the repository backs it with build targets rather than a claim. There are separate TypeScript configurations for browser source output, for React Native and for workerd, the Cloudflare Workers runtime, alongside CommonJS and ESM source configs, and test targets for node, browser and esm. The samples tree covers Bundling, cors, frameworks and web-workers.

Where do I find the API reference for an older azure-sdk-for-js version?

In the versioned developer docs hosted from the repository, while the public developer docs on learn.microsoft.com carry the latest versions. Each package's own README, with code samples and package information, lives under the service folder inside the repository's `/sdk` directory and is also the README shown on the package's npm landing page.

Official sources

  1. Azure/azure-sdk-for-js on GitHub
  2. Issues
  3. License: MIT
  4. README
  5. Releases
Add this badge to your README

If you maintain this project, the badge below links readers to this analysis and shows its maintenance status from the daily GitHub snapshot. Paste the markdown into your README; add ?metric=license or ?metric=stars to the image URL for a different field.

Add this badge to your README

markdown
[![Hysen Labs](https://hysenlabs.com/badge/azure-azure-sdk-for-js.svg)](https://hysenlabs.com/projects/azure-azure-sdk-for-js)