Aller au contenu

Performances

Parcourez correctement les listes, mettez en cache les données stables et parallélisez sans dépasser les limites.

Optimiser les performances d'une intégration de paiement consiste rarement à gagner quelques millisecondes. Il s'agit surtout de ne pas envoyer mille requêtes lorsque trente suffisent, car l'export nocturne consomme le même quota que le checkout utilisé à midi.

Trois sujets couvrent presque tous les besoins : la façon de parcourir une liste, les données que vous pouvez mettre en cache et le nombre d'appels exécutés simultanément.

Parcourir une liste

Tous les endpoints de liste sont paginés. La réponse contient un tableau items accompagné d'un objet meta. Les paramètres sont identiques partout.

ParamètreTypeValeur par défautRemarques
per_pageinteger25De 1 à 100, et 100 convient presque toujours
pageinteger1Mode par décalage
cursorstringMode par curseur, voir Pagination
date_from, date_toYYYY-MM-DDLimites appliquées à created_at
statusstringUn seul statut, pas une liste

Le mode choisi modifie la structure de meta, ce qui provoque souvent des erreurs.

ModeContenu de meta
Décalagecurrent_page, last_page, per_page, total
Curseurper_page, next_cursor, prev_cursor, has_more

Écrire la boucle à la main multiplie les risques : erreur de décalage sur la dernière page, compteur qui n'augmente jamais ou liste qui s'allonge pendant son parcours. Chaque SDK fournit un itérateur qui gère ces cas.

# Offset mode: walk until current_page reaches last_page
curl "https://api.wajub.com/payments?per_page=100&page=1&date_from=2026-09-01&date_to=2026-09-30" \
  -H "Authorization: sk_test.kZ3qP8mWvL2xR7tB5nY4hC6dF9jS1aG0eU3i…" \
  | jq '{ count: (.items | length), page: .meta.current_page, last: .meta.last_page }'

Pour un export complet, procédez par périodes plutôt que par pages. Une période d'un mois produit des requêtes bornées et reproductibles. Relancer une période n'est pas perturbé par les lignes ajoutées depuis. Parcourir profondément les pages d'une table toujours alimentée peut afficher deux fois la même ligne ou en ignorer une.

Mettez en cache ce qui ne change pas

Trois endpoints décrivent la plateforme plutôt que votre compte. Ce sont ceux qu'il est utile de mettre en cache.

RessourceEndpointTTL raisonnable
Canaux de paiementGET /channels1 heure
Pays pris en chargeGET /countries24 heures
Devises prises en chargeGET /currencies24 heures

Ce sont aussi les seules routes accessibles à une clé restreinte sans scope, ce qui montre qu'elles contiennent très peu de données sensibles.

Un cache assez simple pour se passer de bibliothèque
const cache = new Map();

async function cached(key, ttlMs, fetcher) {
  const hit = cache.get(key);
  if (hit && Date.now() - hit.at < ttlMs) return hit.value;

  const value = await fetcher();
  cache.set(key, { value, at: Date.now() });
  return value;
}

const channels = await cached('channels:CM', 3_600_000, () =>
  wajub.global.channels({ country: 'CM' }),
);

Cette règle a une conséquence simple : n'utilisez pas non plus le polling. Interroger chaque paiement toutes les quelques secondes est le moyen le plus courant d'atteindre une limite de requêtes sans rien apprendre. Le webhook vous informe déjà. Webhooks ou polling présente les rares cas où une lecture reste adaptée.

Parallélisez avec une limite

Les lectures séquentielles sont inutilement lentes lorsque les appels sont indépendants. Les lectures parallèles sans limite sont pires : cent requêtes simultanées dépassent un plafond et vous recevez cent réponses 429 au lieu de cent résultats.

Concurrence limitée avec p-limit
import pLimit from 'p-limit';

const limit = pLimit(8);

const payments = await Promise.all(
  paymentIds.map((id) => limit(() => wajub.payments.retrieve(id))),
);

Entre cinq et dix appels simultanés constitue une plage efficace. Elle accélère réellement le traitement tout en restant sous les plafonds par endpoint. Ces plafonds sont plus stricts que le quota de l'équipe et sont les premiers touchés lors d'un pic. Gestion des limites de requêtes présente les valeurs.

Adaptez les délais d'expiration au parcours critique

Le SDK attend 30 secondes avant d'abandonner. Ce délai convient à un job en arrière-plan, mais il est beaucoup trop long pour un client face à un indicateur de chargement. Il rechargera la page et votre handler s'exécutera deux fois.

Un délai plus court lorsqu'une personne attend
const payment = await wajub.payments.create(
  { amount: order.total, currency: order.currency, email: order.email },
  { idempotencyKey: `ORDER-${order.id}`, timeout: 8000 },
);

Réduire le délai d'expiration augmente le risque d'un résultat ambigu, car vous abandonnez des requêtes qui étaient sur le point de réussir. C'est précisément pour cette raison que la clé d'idempotence accompagne le même appel. Sans cette clé, chaque requête lente peut provoquer un double débit.

Mesures à suivre

Quatre mesures indiquent si l'intégration fonctionne correctement. Aucune n'est une moyenne.

SignalÀ surveillerAction
Latence de l'APILe p95, pas la moyenneLa moyenne masque les requêtes qui expirent
Taux de 429Toute valeur durablement supérieure à zéroUne boucle existe, trouvez-la avant qu'elle ne s'aggrave
Taux de 5xxUne hausse, pas un pic isoléUn cas est du bruit, une tendance indique un incident
Retard des webhooksDe l'horodatage de l'événement à son traitementUn écart croissant signifie que votre file prend du retard

Konsole fournit une vue par requête pour un paiement donné. Surveillance explique comment relier ces mesures à votre propre système d'alerte.

Que pensez-vous de ce contenu ?