Skip to content
Learni
View all tutorials
Bases de données NoSQL

Comment scaler Azure Cosmos DB en 2026

Introduction

Azure Cosmos DB est la base de données NoSQL multi-modèle de Microsoft Azure, offrant une scalabilité horizontale illimitée, une distribution globale et des SLAs de 99,999 % de disponibilité. En 2026, avec l'essor des applications IA et serverless, maîtriser Cosmos DB est essentiel pour gérer des charges massives sans downtime. Ce tutoriel avancé vous guide pas à pas pour créer un compte, partitionner des conteneurs, optimiser les RU/s (Request Units), implémenter des queries SQL complexes et configurer des politiques d'indexation avancées via le SDK TypeScript.

Pourquoi c'est crucial ? Une mauvaise partition amène des hotspots et des coûts explosifs ; une indexation sur-optimisée consomme des RU inutiles. Nous illustrons chaque concept avec du code fonctionnel, copier-collable, et des analogies comme un 'répartiteur de charge intelligent' pour le partitioning. À la fin, vous scalerez des millions d'opérations/seconde. Prêt à transformer votre backend en machine scalable ? (128 mots)

Prérequis

  • Compte Azure actif avec abonnement payant (free tier limité pour scaling).
  • Node.js 20+ et npm/yarn installés.
  • Azure CLI installée et authentifiée (az login).
  • Connaissances avancées en TypeScript, async/await et bases NoSQL.
  • Clé d'API Cosmos DB (Endpoint + Primary Key) de votre compte.
  • VS Code avec extension Azure Cosmos DB pour debugging.

Installation du SDK Cosmos DB

terminal
npm init -y
npm install @azure/cosmos @azure/identity dotenv
npm install -D @types/node typescript ts-node

mkdir cosmos-scaling-demo
cd cosmos-scaling-demo

tsc --init --target es2022 --module commonjs --outDir ./dist --rootDir ./src

echo 'COSMOS_ENDPOINT=your-endpoint.azure.com:443/
COSMOS_KEY=your-primary-key==
DATABASE_ID=ScalingDB' > .env

Ce script initialise un projet Node.js avec le SDK officiel @azure/cosmos pour interagir programmatiquement avec Cosmos DB. L'extension @azure/identity gère l'authentification AAD pour la prod ; dotenv charge les secrets. Évitez les clés hardcodées : utilisez Azure Key Vault en prod pour la rotation automatique.

Comprendre la connexion et les bases

La connexion à Cosmos DB utilise un endpoint HTTPS sécurisé et une clé primaire (ou AAD). Pensez-y comme à une 'porte d'entrée globale' : toutes les ops passent par elle, mais le scaling est géré en backend. Avant de scaler, provisionnez un compte avec API SQL (multi-modèle : documents, graph, etc.). Via Portal Azure, activez Analytical Store pour Synapse Link et Serverless pour burst traffic. Vérifiez les RU/s : 400 min par conteneur, scalables à des millions.

Créer la base de données et conteneur partitionné

src/create-db-container.ts
import { CosmosClient } from '@azure/cosmos';
import dotenv from 'dotenv';
dotenv.config();

const client = new CosmosClient({ endpoint: process.env.COSMOS_ENDPOINT!, key: process.env.COSMOS_KEY! });
const databaseId = process.env.DATABASE_ID!;

async function main() {
  const { database } = await client.databases.createIfNotExists({ id: databaseId });
  console.log(`DB créée: ${databaseId}`);

  const containerId = 'Users';
  const partitionKey = { paths: ['/userId'], version: 2 };

  await database.containers.createIfNotExists({
    id: containerId,
    partitionKey,
    indexingPolicy: {
      indexingMode: 'consistent',
      includedPaths: [{ path: '/*' }],
      excludedPaths: [{ path: '/_etag/?' }]
    },
    defaultTtl: 3600
  });
  console.log(`Conteneur partitionné créé: ${containerId}`);
}

main().catch(console.error);

Ce code crée une DB et un conteneur avec partition key /userId (v2 pour hashing logique), indexation consistante et TTL de 1h. La partition évite les hotspots : imaginez des 'silos' par userId pour scaling horizontal. Piège : sans partition, limite 10GB/conteneur ; toujours tester avec charges synthétiques.

Maîtriser le partitioning avancé

Partitioning logique : Choisissez une clé à haute cardinalité (ex: userId, timestamp) pour distribuer uniformément. Cosmos DB auto-repartit les partitions physiques (150GB max chacune). Pour cross-partition queries, limitez avec EnableCrossPartitionQuery: false si possible. Analogy : comme un restaurant avec tables par groupe – trop de clients par table = bottleneck.

Insérer des données massives et query pointue

src/insert-query.ts
import { CosmosClient } from '@azure/cosmos';
import dotenv from 'dotenv';
dotenv.config();

const client = new CosmosClient({ endpoint: process.env.COSMOS_ENDPOINT!, key: process.env.COSMOS_KEY! });
const database = client.database(process.env.DATABASE_ID!);
const container = database.container('Users');

async function main() {
  // Bulk insert (100 items)
  const items = [];
  for (let i = 0; i < 100; i++) {
    items.push({
      id: `user${i}`,
      userId: `userPartition${Math.floor(i / 10)}`,
      name: `User ${i}`,
      score: Math.random() * 100,
      tags: ['premium', 'active'],
      timestamp: new Date().toISOString()
    });
  }
  const { result: inserted } = await container.items.createMany(items);
  console.log(`${inserted.length} items insérés`);

  // Point query (intra-partition)
  const { resources: user } = await container.item('user0', 'userPartition0').read();
  console.log('User retrouvé:', user);
}

main().catch(console.error);

Utilisez createMany pour bulk ops (jusqu'à 500 items/req, 5MB max) afin de minimiser les RU/s. Query pointue avec id + partitionKey est la plus efficace (1 RU). Évitez les scans : toujours spécifiez partitionKey pour <10 RU vs 1000+ en cross-partition.

Query SQL avancée avec agrégats

query.sql
SELECT c.userId, AVG(c.score) AS avgScore, COUNT(c.id) AS userCount
FROM c
WHERE c.tags @> ['premium'] AND c.timestamp > '2026-01-01T00:00:00Z'
GROUP BY c.userId
ORDER BY avgScore DESC
OFFSET 0 LIMIT 10

Cette query SQL utilise JSON operators (@>), filtre temporel, GROUP BY et pagination (OFFSET/LIMIT). Efficace avec index sur /tags et /timestamp. Coût : ~50 RU pour 1k items ; testez dans Data Explorer pour profiler.

Queries et optimisation RU/s

Exécutez la query via SDK avec container.items.query(querySpec). Profilez les RU dans le portail (Metrics tab). Astuces : ORDER BY sur partition key, éviter SELECT * (utilisez VALUE ou projection). Pour analytical, activez Spark Connector.

Exécuter la query SQL dans TypeScript

src/advanced-query.ts
import { CosmosClient, SqlQuerySpec } from '@azure/cosmos';
import dotenv from 'dotenv';
dotenv.config();

const client = new CosmosClient({ endpoint: process.env.COSMOS_ENDPOINT!, key: process.env.COSMOS_KEY! });
const container = client.database(process.env.DATABASE_ID!).container('Users');

const querySpec: SqlQuerySpec = {
  query: "SELECT c.userId, AVG(c.score) AS avgScore FROM c WHERE c.tags @> ['premium'] GROUP BY c.userId"
};

async function main() {
  const { resources, requestCharge } = await container.items.query(querySpec).fetchAll();
  console.log(`Résultats:`, resources);
  console.log(`RU consommés: ${requestCharge}`);
}

main().catch(console.error);

fetchAll() pour petits résultats ; utilisez itérateurs pour >100k. Loggez requestCharge pour tuning. Piège : cross-partition GROUP BY peut exploser les RU – partitionnez par userId pour intra-partition.

Politique d'indexation custom (JSON)

indexing-policy.json
{
  "indexingMode": "consistent",
  "automatic": true,
  "includedPaths": [
    { "path": "/userId/?", "indexes": [{ "kind": "Hash", "dataType": "String", "precision": -1 }] },
    { "path": "/score/?", "indexes": [{ "kind": "Number", "dataType": "Number", "precision": -1 }] },
    { "path": "/tags/?" }
  ],
  "excludedPaths": [
    { "path": "/timestamp/?" },
    { "path": "/*" }
  ],
  "spatialIndexes": [],
  "compositeIndexes": [
    [
      { "path": "/userId", "order": "ascending" },
      { "path": "/score", "order": "descending" }
    ]
  ]
}

Cette policy indexe sélectivement (Hash pour strings, Number pour score) et exclut timestamp pour économies RU (10-20%). Composite pour ORDER BY userId+score. Appliquez-la lors du createIfNotExists ; rebuild coûteux sur gros conteneurs.

Change Feed pour scaling événementiel

src/change-feed.ts
import { CosmosClient, ChangeFeedIterator } from '@azure/cosmos';
import dotenv from 'dotenv';
dotenv.config();

const client = new CosmosClient({ endpoint: process.env.COSMOS_ENDPOINT!, key: process.env.COSMOS_KEY! });
const container = client.database(process.env.DATABASE_ID!).container('Users');

async function main() {
  const iterator: ChangeFeedIterator<any> = container.items.readChangeFeed({
    startFromBeginning: false
  });

  let count = 0;
  while (!(await iterator.hasMoreResults())) {
    const response = await iterator.fetchNext();
    count += response.resources.length;
    console.log(`Changements lus: ${count}`);
    // Traitez pour Azure Functions/Event Hubs
  }
}

main().catch(console.error);

Change Feed capture les upserts/deletes en ordre par partition, parfait pour CDC (Change Data Capture) vers Kafka ou Functions. Scaling : parallèle par partition. Limite : lease container requis pour multi-instances.

Bonnes pratiques

  • Choisissez RU autoscale (10x-100x max) pour workloads variables ; monitor via Metrics API.
  • Implémentez fan-out : queries par partition en parallèle avec Promise.all.
  • Utilisez Serverless v2 pour <5% utilisation ; migrez vers provisioned pour prédictible.
  • Activez multi-region writes pour latence <10ms globale.
  • Profilez toujours : ciblez <5 RU/query avec indexing policy minimaliste.

Erreurs courantes à éviter

  • Hot partitions : clé à faible cardinalité (ex: /country) → uniformisez avec composite (userId + region).
  • Cross-partition queries excessives : coût x10 ; refactorisez en app-level aggregation.
  • Indexation full : double les RU d'insert ; excluez champs non-queriés.
  • TTL sur partition key : peut causer rebalancing coûteux ; testez avec Autopilot.

Pour aller plus loin