- @azure/cosmos (TypeScript/JavaScript)
- Data plane SDK for Azure Cosmos DB NoSQL API operations — CRUD on documents, queries, bulk operations.
- ⚠️ Data vs Management Plane
- This SDK (@azure/cosmos)
-
- CRUD operations on documents, queries, stored procedures
- Management SDK (@azure/arm-cosmosdb)
-
- Create accounts, databases, containers via ARM
- Installation
- npm
- install
- @azure/cosmos @azure/identity
- Current Version
-
- 4.9.0
- Node.js
-
= 20.0.0 Environment Variables COSMOS_ENDPOINT = https:// < account
.documents.azure.com:443/ COSMOS_DATABASE = < database-name
COSMOS_CONTAINER
< container-name
For key-based auth only (prefer AAD)
COSMOS_KEY
< account-key
Authentication AAD with DefaultAzureCredential (Recommended) import { CosmosClient } from "@azure/cosmos" ; import { DefaultAzureCredential } from "@azure/identity" ; const client = new CosmosClient ( { endpoint : process . env . COSMOS_ENDPOINT ! , aadCredentials : new DefaultAzureCredential ( ) , } ) ; Key-Based Authentication import { CosmosClient } from "@azure/cosmos" ; // Option 1: Endpoint + Key const client = new CosmosClient ( { endpoint : process . env . COSMOS_ENDPOINT ! , key : process . env . COSMOS_KEY ! , } ) ; // Option 2: Connection String const client = new CosmosClient ( process . env . COSMOS_CONNECTION_STRING ! ) ; Resource Hierarchy CosmosClient └── Database └── Container ├── Items (documents) ├── Scripts (stored procedures, triggers, UDFs) └── Conflicts Core Operations Database & Container Setup const { database } = await client . databases . createIfNotExists ( { id : "my-database" , } ) ; const { container } = await database . containers . createIfNotExists ( { id : "my-container" , partitionKey : { paths : [ "/partitionKey" ] } , } ) ; Create Document interface Product { id : string ; partitionKey : string ; name : string ; price : number ; } const item : Product = { id : "product-1" , partitionKey : "electronics" , name : "Laptop" , price : 999.99 , } ; const { resource } = await container . items . create < Product
( item ) ; Read Document const { resource } = await container . item ( "product-1" , "electronics" ) // id, partitionKey . read < Product
( ) ; if ( resource ) { console . log ( resource . name ) ; } Update Document (Replace) const { resource : existing } = await container . item ( "product-1" , "electronics" ) . read < Product
( ) ; if ( existing ) { existing . price = 899.99 ; const { resource : updated } = await container . item ( "product-1" , "electronics" ) . replace < Product
( existing ) ; } Upsert Document const item : Product = { id : "product-1" , partitionKey : "electronics" , name : "Laptop Pro" , price : 1299.99 , } ; const { resource } = await container . items . upsert < Product
( item ) ; Delete Document await container . item ( "product-1" , "electronics" ) . delete ( ) ; Patch Document (Partial Update) import { PatchOperation } from "@azure/cosmos" ; const operations : PatchOperation [ ] = [ { op : "replace" , path : "/price" , value : 799.99 } , { op : "add" , path : "/discount" , value : true } , { op : "remove" , path : "/oldField" } , ] ; const { resource } = await container . item ( "product-1" , "electronics" ) . patch < Product
( operations ) ; Queries Simple Query const { resources } = await container . items . query < Product
( "SELECT * FROM c WHERE c.price < 1000" ) . fetchAll ( ) ; Parameterized Query (Recommended) import { SqlQuerySpec } from "@azure/cosmos" ; const querySpec : SqlQuerySpec = { query : "SELECT * FROM c WHERE c.partitionKey = @category AND c.price < @maxPrice" , parameters : [ { name : "@category" , value : "electronics" } , { name : "@maxPrice" , value : 1000 } , ] , } ; const { resources } = await container . items . query < Product
( querySpec ) . fetchAll ( ) ; Query with Pagination const queryIterator = container . items . query < Product
( querySpec , { maxItemCount : 10 , // Items per page } ) ; while ( queryIterator . hasMoreResults ( ) ) { const { resources , continuationToken } = await queryIterator . fetchNext ( ) ; console . log (
Page with ${ resources ?. length } items) ; // Use continuationToken for next page if needed } Cross-Partition Query const { resources } = await container . items . query < Product( "SELECT * FROM c WHERE c.price > 500" , { enableCrossPartitionQuery : true } ) . fetchAll ( ) ; Bulk Operations Execute Bulk Operations import { BulkOperationType , OperationInput } from "@azure/cosmos" ; const operations : OperationInput [ ] = [ { operationType : BulkOperationType . Create , resourceBody : { id : "1" , partitionKey : "cat-a" , name : "Item 1" } , } , { operationType : BulkOperationType . Upsert , resourceBody : { id : "2" , partitionKey : "cat-a" , name : "Item 2" } , } , { operationType : BulkOperationType . Read , id : "3" , partitionKey : "cat-b" , } , { operationType : BulkOperationType . Replace , id : "4" , partitionKey : "cat-b" , resourceBody : { id : "4" , partitionKey : "cat-b" , name : "Updated" } , } , { operationType : BulkOperationType . Delete , id : "5" , partitionKey : "cat-c" , } , { operationType : BulkOperationType . Patch , id : "6" , partitionKey : "cat-c" , resourceBody : { operations : [ { op : "replace" , path : "/name" , value : "Patched" } ] , } , } , ] ; const response = await container . items . executeBulkOperations ( operations ) ; response . forEach ( ( result , index ) => { if ( result . statusCode = 200 && result . statusCode < 300 ) { console . log (
Operation ${ index } succeeded) ; } else { console . error (Operation ${ index } failed: ${ result . statusCode }) ; } } ) ; Partition Keys Simple Partition Key const { container } = await database . containers . createIfNotExists ( { id : "products" , partitionKey : { paths : [ "/category" ] } , } ) ; Hierarchical Partition Key (MultiHash) import { PartitionKeyDefinitionVersion , PartitionKeyKind } from "@azure/cosmos" ; const { container } = await database . containers . createIfNotExists ( { id : "orders" , partitionKey : { paths : [ "/tenantId" , "/userId" , "/sessionId" ] , version : PartitionKeyDefinitionVersion . V2 , kind : PartitionKeyKind . MultiHash , } , } ) ; // Operations require array of partition key values const { resource } = await container . items . create ( { id : "order-1" , tenantId : "tenant-a" , userId : "user-123" , sessionId : "session-xyz" , total : 99.99 , } ) ; // Read with hierarchical partition key const { resource : order } = await container . item ( "order-1" , [ "tenant-a" , "user-123" , "session-xyz" ] ) . read ( ) ; Error Handling import { ErrorResponse } from "@azure/cosmos" ; try { const { resource } = await container . item ( "missing" , "pk" ) . read ( ) ; } catch ( error ) { if ( error instanceof ErrorResponse ) { switch ( error . code ) { case 404 : console . log ( "Document not found" ) ; break ; case 409 : console . log ( "Conflict - document already exists" ) ; break ; case 412 : console . log ( "Precondition failed (ETag mismatch)" ) ; break ; case 429 : console . log ( "Rate limited - retry after:" , error . retryAfterInMs ) ; break ; default : console . error (Cosmos error ${ error . code } : ${ error . message }) ; } } throw error ; } Optimistic Concurrency (ETags) // Read with ETag const { resource , etag } = await container . item ( "product-1" , "electronics" ) . read < Product( ) ; if ( resource && etag ) { resource . price = 899.99 ; try { // Replace only if ETag matches await container . item ( "product-1" , "electronics" ) . replace ( resource , { accessCondition : { type : "IfMatch" , condition : etag } , } ) ; } catch ( error ) { if ( error instanceof ErrorResponse && error . code === 412 ) { console . log ( "Document was modified by another process" ) ; } } } TypeScript Types Reference import { // Client & Resources CosmosClient , Database , Container , Item , Items , // Operations OperationInput , BulkOperationType , PatchOperation , // Queries SqlQuerySpec , SqlParameter , FeedOptions , // Partition Keys PartitionKeyDefinition , PartitionKeyDefinitionVersion , PartitionKeyKind , // Responses ItemResponse , FeedResponse , ResourceResponse , // Errors ErrorResponse , } from "@azure/cosmos" ; Best Practices Use AAD authentication — Prefer DefaultAzureCredential over keys Always use parameterized queries — Prevents injection, improves plan caching Specify partition key — Avoid cross-partition queries when possible Use bulk operations — For multiple writes, use executeBulkOperations Handle 429 errors — Implement retry logic with exponential backoff Use ETags for concurrency — Prevent lost updates in concurrent scenarios Close client on shutdown — Call client.dispose() in cleanup Common Patterns Service Layer Pattern export class ProductService { private container : Container ; constructor ( client : CosmosClient ) { this . container = client . database ( process . env . COSMOS_DATABASE ! ) . container ( process . env . COSMOS_CONTAINER ! ) ; } async getById ( id : string , category : string ) : Promise < Product | null
{ try { const { resource } = await this . container . item ( id , category ) . read < Product
( ) ; return resource ?? null ; } catch ( error ) { if ( error instanceof ErrorResponse && error . code === 404 ) { return null ; } throw error ; } } async create ( product : Omit < Product , "id"
) : Promise < Product
{ const item = { ... product , id : crypto . randomUUID ( ) } ; const { resource } = await this . container . items . create < Product
( item ) ; return resource ! ; } async findByCategory ( category : string ) : Promise < Product [ ]
{ const querySpec : SqlQuerySpec = { query : "SELECT * FROM c WHERE c.partitionKey = @category" , parameters : [ { name : "@category" , value : category } ] , } ; const { resources } = await this . container . items . query < Product
( querySpec ) . fetchAll ( ) ; return resources ; } } Related SDKs SDK Purpose Install @azure/cosmos Data plane (this SDK) npm install @azure/cosmos @azure/arm-cosmosdb Management plane (ARM) npm install @azure/arm-cosmosdb @azure/identity Authentication npm install @azure/identity When to Use This skill is applicable to execute the workflow or actions described in the overview.