ediverse Explorer la plateforme

À la une PEPPOL BIS Billing 3.0 L’obligation européenne d’e-invoicing arrive : France sept 2026, Belgique janv 2026, Allemagne 2025.

Token Bucket Rate Limiter

L'algorithme du Rate Limiter qui autorise des bursts contrôlés sans renoncer à un débit soutenu maîtrisé : le détail qui transforme une politique en chiffre lisible.

Problème

Le Rate Limiter de base limite par fenêtre fixe (« 100 requêtes par minute »). Problème : en bordure de fenêtre, on peut tirer 100 requêtes à 12:00:59 et 100 à 12:01:00, soit 200 en une seconde — saturation. Autre problème : si on impose « jamais plus de 2 par seconde », un envoi de batch légitime de 50 INVOIC en une seconde, qui tient parfaitement en moyenne sur la journée, est rejeté. Il faut un algorithme qui distingue débit soutenu et burst, et qui ne crée pas d'effet de bord temporel.

Forces

  • Les pics légitimes existent. Fin de mois, synchronisation matinale, batches partenaires.
  • Le débit soutenu doit être borné. Sur 24h, on ne veut pas dépasser X millions de requêtes.
  • Le calcul doit être simple. Le Rate Limiter tourne avant tout traitement, doit être O(1).
  • Le SLA partenaire doit être calculable. « Tu peux burster à 500, débit moyen 100/s » est contractuel.

Solution

Implémenter un seau de jetons de capacité maximale N (taille du burst autorisé), rechargé à un taux R jetons/seconde (débit soutenu). Chaque requête consomme 1 jeton (ou k jetons selon coût). Si le seau est vide, la requête est rejetée immédiatement (HTTP 429, Retry-After). Le calcul à l'arrivée d'une requête à l'instant t : tokens = min(N, tokens_prev + (t - t_prev) × R), puis tokens -= 1 si autorisé. Algorithme O(1), seulement deux floats à stocker par compteur. Implémentations : Bucket4j (Java), Cloudflare Edge Workers, Kong, NGINX limit_req_zone, AWS API Gateway.

   Recharge automatique
   R = 100 jetons/sec
         │
         ▼
   ┌──────────────┐
   │  Seau N=500  │  capacité max (burst)
   │  ●●●●●●●●●● │  jetons actuellement
   │  ●●●●●●●●●● │
   └──────────────┘
         │ consume 1 par requête
         ▼
   requête partenaire
         │
   si seau vide :
   ┌──────────────────────────┐
   │ HTTP 429 Too Many Req    │
   │ Retry-After: N           │
   └──────────────────────────┘

Implémentation EDI

Cas concret : l'API REST d'un hub EDI accepte des INVOIC d'un partenaire Walmart. Le contrat dit : 100 INVOIC/seconde soutenu, burst 500. Sur Kong (API Gateway), plugin rate-limiting-advanced en mode sliding window ou un module Lua token-bucket : limit=500, rate=100/s, identifier=consumer.partner_id. Walmart envoie un batch de 480 messages à 14h32:00 : tous passent (seau de 500 jetons, 480 consommés). À 14h32:01, il en reste 20 + 100 rechargés = 120, etc. Si Walmart pousse 600 à 14h32:00, les 100 derniers reçoivent HTTP 429 Retry-After: 1. Côté Kafka producer : quota.producer.byte.rate par client.id, équivalent token bucket sur octets. Côté PEPPOL : norme OpenPEPPOL impose un débit max par Access Point — typiquement implémenté en token bucket.

Paramètres pratiques

  • R (refill rate) : la moyenne soutenue souhaitée par seconde. Doit correspondre à la capacité de l'aval.
  • N (bucket size) : combien on tolère en burst. Souvent N = 5×R à 10×R.
  • Identifier : par partnerId, par apiKey, par IP. Choisir la clé du contrat.
  • Storage : Redis cluster pour le partage multi-instance (avec SCRIPT Lua pour atomicité), mémoire locale si single-node.
  • Response on reject : HTTP 429, Retry-After: N (RFC 6585), header X-RateLimit-Remaining.

Anti-patterns

  • Token bucket sans persistance. Restart du service → seau réinitialisé → burst libre.
  • Token bucket multi-instance sans coordination. Chaque instance a son seau : le partenaire peut dépasser k×R en attaquant k instances. Centraliser via Redis.
  • Burst N trop grand. Si N=10000 pour R=100, le pattern n'a aucun effet — le burst max sature toujours.
  • R indépendant des partenaires. Un seul rate limit global pour tous : un partenaire bavard sature le quota de tous.

Patterns liés

  • Rate Limiter — le pattern parent.
  • Back-pressure — le rate limiter est une back-pressure contractuelle aval.
  • Bulkhead — couplé : un token bucket par compartiment.
  • Circuit Breaker — complémentaire : si l'aval échoue, ne pas consommer les jetons.

Sources