Skip to content
Learni
Voir tous les tutoriels
Bases de données NoSQL

Comment scaler Azure Cosmos DB en 2026

Read in English

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