DIDOES ITEndpoint Engineering← Tous les articles

Technologie IT / Endpoint & Automation

Microsoft Graph : maîtriser pagination, batching et throttling

Un appel Graph qui fonctionne sur dix objets peut échouer à l’échelle d’un tenant. Je construis la robustesse autour de trois mécanismes : pagination, lots JSON et régulation 429.

À propos des exemples

Je publie les diagnostics en niveau 1 et les exemples de remédiation au minimum en niveau 2. Ils restent pédagogiques, non testés et ne doivent pas être utilisés tels quels. Avant tout essai réel, adaptez-les au contexte, utilisez la simulation quand elle existe et validez le rollback sur un pilote représentatif.

01

Résumé

La pagination exige de suivre @odata.nextLink jusqu’à son absence. Recalculer l’URL ou ignorer la page suivante produit un export incomplet sans forcément générer d’erreur.

Le JSON batching combine jusqu’à vingt sous-requêtes dans un appel HTTP, mais chaque sous-requête est évaluée séparément. Le lot peut répondre 200 alors que certaines réponses internes sont 429 ou en erreur.

Lors d’un throttling, le client respecte Retry-After. Sans en-tête, il utilise un backoff exponentiel borné avec jitter. Les SDK gèrent certains retries individuels, mais les sous-requêtes batchées échouées doivent être reconstruites explicitement.

La pagination exige de suivre @odata.nextLink jusqu’à son absence. Recalculer l’URL ou ignorer la page suivante produit un export incomplet sans forcément générer d’erreur.
02

Contexte, objectif et périmètre

Les limites Graph varient par service, type de ressource, tenant et nature des opérations. Une boucle agressive de polling ou de writes peut pénaliser l’application et le tenant.

La robustesse inclut aussi permissions minimales, authentification, corrélation, idempotence et gestion des erreurs. Le batching réduit les allers-retours, pas les limites de chaque service.

Je traite « Pagination, batching et throttling Graph » comme une chaîne de preuves et non comme une succession de boutons à cliquer. Une action n’est considérée comme réussie que lorsque le résultat est visible au niveau attendu : configuration du service, état reçu par le poste, traitement local, puis remontée cohérente dans les outils d’administration. Cette séparation évite de confondre une affectation valide avec une exécution terminée.

Je conserve systématiquement les heures en UTC et en heure locale, l’identité de l’appareil, le contexte utilisateur ou système, la version de Windows et la version des composants concernés. Sans ces repères, deux événements semblables peuvent appartenir à des cycles différents. Les exemples de journaux sont anonymisés et les identifiants techniques doivent l’être avant tout partage.

Pour expliquer la technologie, je sépare le plan de contrôle, le transport, les composants locaux et les données de résultat. Cette lecture évite d’attribuer au portail une décision prise par Windows, ou à un agent local une limitation qui appartient en réalité au service cloud, à la licence ou au modèle d’affectation.

Les détails internes observés dans les journaux ou le registre servent à établir une hypothèse de diagnostic. Ils ne deviennent pas pour autant une interface publique stable. Toute automatisation durable doit s’appuyer sur une API ou une configuration officiellement supportée, puis être revalidée quand la version du service ou du client change.

  • Objectif : lire une collection complète
  • Objectif : traiter chaque réponse d’un batch
  • Objectif : reprendre après 429 sans tempête de retries
  • Périmètre : Microsoft Graph v1.0 en priorité
  • Périmètre : REST et PowerShell
  • Périmètre : lectures volumineuses et lots JSON
03

Architecture et fonctionnement général

Une collection Graph retourne value et peut fournir @odata.nextLink. Ce lien est opaque : je l’utilise tel quel, car il peut contenir skiptoken, filtres encodés ou état de service.

Un batch POST /$batch contient des requêtes avec id, method, url et éventuellement body/headers. L’ordre n’est pas garanti sans dependsOn. Vingt requêtes constituent la limite d’un lot JSON Graph.

Le throttling retourne généralement 429 et Retry-After. Un batch HTTP 200 n’indique que l’acceptation de l’enveloppe ; le client inspecte status et headers de chaque réponse avant de marquer le lot réussi.

FLUXChaîne fonctionnelle — Pagination, batching et throttling Graph
  1. RequestURI, permission, filtre et identifiant de corrélation.
  2. Page/BatchnextLink ou enveloppe de sous-requêtes.
  3. ResponseStatut global et statuts individuels.
  4. RetryRetry-After, backoff, jitter et reprise idempotente.

Chaque étape doit produire sa propre preuve. Un succès en amont ne garantit pas que les étapes suivantes ont terminé leur traitement.

04

Prérequis techniques et préparation

Avant toute mise en œuvre, je fige le périmètre de test et je capture l’état initial. Cette photographie comprend les versions, les affectations, les autorités de gestion, les dépendances et les exceptions connues. Elle sert autant à interpréter le résultat qu’à construire le retour arrière.

Je vérifie les prérequis sur un appareil réellement représentatif. Une console qui autorise la création d’un profil ne prouve ni l’éligibilité du poste, ni la disponibilité effective de la fonctionnalité dans le tenant. Les prérequis réseau, licence, identité et système doivent tous être confirmés.

  • application Entra et permissions minimales
  • endpoint et version vérifiés
  • secret absent du code et méthode d’authentification sûre
  • opérations d’écriture idempotentes ou protégées
  • journal corrélé et limites de retry
05

Procédure de mise en œuvre

La procédure suivante est volontairement découpée en points de contrôle. Je ne poursuis pas lorsqu’un résultat attendu manque : continuer masquerait la première divergence et produirait des symptômes secondaires plus difficiles à interpréter.

Les noms de groupes, profils, applications et fichiers sont des exemples. Je les remplace par les conventions de l’organisation, je documente la population ciblée et je conserve une preuve avant/après pour chaque changement.

PROCÉDUREMise en œuvre contrôlée
  1. 01Valider une requête minimale
    Emplacement
    Graph Explorer ou pilote
    Commande / configuration
    GET endpoint?$top=<petit nombre>
    Résultat attendu
    Première page et nextLink compris.
    Vérification
    Permissions et schéma conformes.
    Impact
    Lecture seule.
    Retour arrière
    Aucun.
  2. 02Implémenter la pagination
    Emplacement
    Client PowerShell
    Commande / configuration
    Boucler sur @odata.nextLink jusqu’à null.
    Résultat attendu
    Toutes les pages collectées.
    Vérification
    Compte comparé à une source connue.
    Impact
    Charge de lecture contrôlée.
    Retour arrière
    Arrêter le job et supprimer l’export incomplet.
  3. 03Créer des batches bornés
    Emplacement
    POST /$batch
    Commande / configuration
    Découper en groupes de vingt maximum et attribuer un id unique.
    Résultat attendu
    Chaque sous-réponse corrélable.
    Vérification
    Aucun id manquant ou dupliqué.
    Impact
    Réduction des allers-retours.
    Retour arrière
    Revenir aux appels unitaires pour isoler un défaut.
  4. 04Rejouer seulement les échecs
    Emplacement
    Gestionnaire de retry
    Commande / configuration
    Lire status/Retry-After par sous-réponse et reconstruire le lot.
    Résultat attendu
    Pas de replay des succès.
    Vérification
    Journal montre attente et nombre de tentatives.
    Impact
    Charge maîtrisée.
    Retour arrière
    Stopper après la limite et reprendre depuis checkpoint.

La généralisation n’est autorisée qu’après observation du pilote pendant la durée définie dans le plan de changement.

06

Pagination sûre

Je conserve les résultats page par page et un compteur. Si une page échoue, je garde le dernier nextLink validé pour reprendre sans recommencer tout le tenant.

Je n’ajoute pas manuellement $skip lorsque le service fournit nextLink. La forme de pagination appartient à l’endpoint.

Les filtres côté serveur réduisent le volume lorsqu’ils sont supportés. Je vérifie leurs capacités sur la documentation de la ressource et je n’interprète pas un filtre ignoré comme une preuve d’absence.

07

Batching et réponses partielles

Chaque request reçoit un id, utilisé pour relier réponse, objet métier et opération. dependsOn exprime un ordre, mais une dépendance échouée doit être traitée explicitement.

Je sépare les lots de lecture et d’écriture. Pour les writes, je prévois la répétition partielle et je vérifie l’état avant replay afin d’éviter doublons ou modifications concurrentes.

Les 429 internes fournissent parfois retry-after dans le contenu de la sous-réponse. Le SDK ne rejoue pas automatiquement ces éléments batchés ; mon code extrait le délai et ne reconstruit que les échecs transitoires.

08

Backoff, observabilité et limites

Retry-After est prioritaire. À défaut, le backoff exponentiel augmente l’attente à chaque tentative, ajoute un jitter et respecte un plafond. Une boucle infinie est interdite.

Je journalise request-id, client-request-id, endpoint, statut, tentative, durée et nombre d’objets sans consigner token ou données sensibles.

Pour une extraction massive, je vérifie si Graph Data Connect ou un service de reporting est plus adapté. Réduire artificiellement le délai entre requêtes ne transforme pas Graph REST en pipeline de données bulk.

09

Scripts, commandes et exemples de lecture

Les commandes présentées servent à observer ou illustrer le fonctionnement. Les scripts de diagnostic restent de niveau 1, avec arrêt sur erreur et gestion globale de l’exception. Ils ne modifient pas le poste. Une remédiation serait au minimum de niveau 2, avec mode de simulation, journalisation adaptée au test et comportement de rollback explicitement validé.

Je lis toujours la sortie avec le contexte d’exécution. Une commande lancée dans la session de l’utilisateur ne voit pas nécessairement les mêmes certificats, chemins, variables, applications ou ruches de registre qu’un processus exécuté par l’Intune Management Extension sous SYSTEM.

POWERSHELLPagination Graph en lecture seule — niveau 1
# Exemple pédagogique non testé — niveau 1
$ErrorActionPreference = 'Stop'
try {
  $uri = 'https://graph.microsoft.com/v1.0/deviceManagement/managedDevices?$top=100'
  $items = [System.Collections.Generic.List[object]]::new()
  while ($uri) {
    $page = Invoke-MgGraphRequest -Method GET -Uri $uri
    foreach ($item in $page.value) { $items.Add($item) }
    $uri = $page.'@odata.nextLink'
  }
  $items
}
catch { Write-Error "Lecture Graph impossible : $($_.Exception.Message)"; exit 1 }

Les permissions et propriétés doivent être adaptées à l’endpoint. Ce diagnostic ne modifie aucune ressource.

LOGRetry batch corrélé
BatchId=20260818-01 HttpStatus=200 Responses=20
SubRequest=07 Status=429 RetryAfter=12 Action=QueueRetry
SubRequest=12 Status=503 RetryAfter=absent Backoff=8.4
RetryBatch=20260818-01-R1 Requests=2 Delay=12
Result Success=20 Failed=0 Attempts=2

Exemple fictif : le lot global est 200 malgré deux sous-requêtes à rejouer.

10

Validation et critères de contrôle

Je valide d’abord le résultat technique sur le poste, puis sa remontée dans le service. Le portail peut conserver un état ancien pendant un certain temps ; inversement, un état vert dans la console ne dispense pas de contrôler l’artefact local réellement attendu.

Le critère GO exige un résultat reproductible, une absence de régression sur les fonctions voisines, une documentation à jour et un retour arrière démontré. Le critère NO-GO s’applique dès qu’une dépendance n’est pas maîtrisée, qu’une partie du parc réagit différemment ou que l’état final ne peut pas être prouvé.

  • toutes pages parcourues
  • lots de vingt maximum
  • chaque sous-réponse inspectée
  • Retry-After respecté
  • limite de tentatives
  • aucun secret dans logs
11

Journaux, diagnostic et constitution des preuves

Je ne journalise jamais Authorization. Je conserve les identifiants de corrélation, les statuts, Retry-After, le nombre d’objets et l’endpoint sans paramètres sensibles.

Un résultat incomplet sans erreur peut provenir d’une pagination interrompue. Je compare le nombre de pages, le compteur d’objets et la présence finale de nextLink avant de publier l’export.

  • endpoint/version
  • permissions consenties
  • nombre de pages
  • nextLink final absent
  • statut par sous-requête
  • Retry-After et tentatives
  • request-id/client-request-id
12

Dépannage : symptômes, preuves et corrections

Je pars de la colonne Symptôme, mais je ne choisis jamais une correction sur ce seul indice. La colonne Preuve indique l’élément qui doit confirmer la cause. Si cette preuve manque, l’hypothèse reste ouverte et l’action proposée ne doit pas être appliquée comme une recette automatique.

Après correction, je reproduis le scénario initial et je compare les mêmes points de mesure. Un changement de symptôme n’est pas toujours une résolution : il peut simplement indiquer que le traitement progresse jusqu’à une nouvelle phase. La chronologie complète reste donc la référence.

MATRICEMatrice de diagnostic
SymptômeCause à confirmerPreuve recherchéeCorrection ciblée
Export incompletnextLink ignoréCompteur pages et nextLinkBoucler sur le lien opaque
Batch 200 mais objets manquentSous-réponses en erreurStatus par idRejouer seulement les échecs
429 répétésPolling ou writes excessifsRetry-After et volumeRéduire fréquence et respecter délai
403Permission ou type de jetonScopes/roles et endpointAppliquer moindre privilège requis
Doublons après retryWrite non idempotentJournal corrélé et état ressourceVérifier avant replay et ajouter garde

Les causes sont des hypothèses jusqu’à leur confirmation par une preuve locale ou une donnée de service corrélée.

13

Retour arrière et points de vigilance

Le retour arrière ne consiste pas seulement à retirer une affectation. Je restaure l’autorité précédente, la configuration ou la version attendue, puis je vérifie que le poste a effectivement reçu et appliqué ce nouvel état. Les caches et délais de remontée sont documentés au lieu d’être interprétés comme une absence de rollback.

Je conserve les preuves du pilote, le motif de la décision et les écarts rencontrés. Si le service cloud ou une interface évolue, je réévalue les étapes avant une nouvelle vague. Aucun succès obtenu uniquement sur le poste de développement ne constitue une validation de production.

  • Rollback : arrêter le job au seuil
  • Rollback : reprendre depuis checkpoint
  • Rollback : restaurer les écritures uniquement via procédure métier testée
  • Vigilance : v1.0 avant beta
  • Vigilance : batching ne contourne pas throttling
  • Vigilance : Graph Data Connect pour bulk adapté
  • Vigilance : écritures réelles au minimum niveau 2 et souvent niveau 3/4
R

Repères d’utilisation

Cette analyse propose une méthode opérationnelle et un cadre de décision. Avant toute application à grande échelle, vérifiez les versions, les licences et les comportements sur un environnement pilote représentatif de votre contexte.

Références techniques publiques

J’ai privilégié la documentation Microsoft pour les comportements contractuels. Les retours terrain complètent l’observation, sans remplacer la documentation de support.

Microsoft GraphPowerShellPaginationBatchThrottlingRetry-After

Continuer la lecture

Modern Workplace LabOMA-DM et WinDC en double inscriptionEndpoint LabDiagnostic complet des applications Win32