Dans un pipeline distribué, la backpressure (ou contre-pression) désigne un mécanisme de contrôle de flux qui régule le débit des données entre les étapes ou nœuds successifs. Elle intervient lorsque le consommateur (nœud aval) ne peut pas traiter les données au rythme où le producteur (nœud amont) les émet : la contrainte de capacité du maillon lent est propagée en amont pour ralentir la source.

Mécanisme et objectifs

Signal de ralentissement

Quand un nœud aval sature (mémoire, CPU, latence d'E/S), il propage explicitement ou implicitement un signal qui réduit ou suspend l'émission en amont. Cela évite :
la perte de données (débordement de tampon) ;
la croissance illimitée des files d'attente et l'explosion de la latence ;
l'effondrement du système (ex. : OutOfMemoryError).

Équilibrage dynamique

Le débit global du pipeline s'aligne sur la capacité du goulet d'étranglement (bottleneck), ce qui garantit un régime stable et borné en ressources.

Implémentations courantes

Files d'attente bornées : le producteur est bloqué (ou mis en attente) lorsque la file est pleine.
Protocoles réactifs (Reactive Streams, RSocket) : demande explicite du consommateur via request(n) — modèle pull avec crédit.
Fenêtre glissante / crédits : limitation du nombre de messages ou d'octets en transit (principe repris de TCP).
Throttling / rate limiting : réduction du débit en fonction de métriques observées (latence, profondeur de file, taux d'erreur).

Exemple concret
Dans un pipeline de streaming :
Apache Kafka repose sur un modèle pull : le consommateur appelle poll() à son propre rythme, ce qui constitue une backpressure naturelle — les messages non consommés restent simplement dans le log du topic, dont la rétention borne le stockage. Kafka offre par ailleurs des quotas (débit producteur/consommateur) pour imposer une limitation côté broker.
Apache Flink propage la contre-pression de proche en proche via ses tampons réseau : une tâche aval saturée cesse d'accorder des crédits de tampon, ce qui bloque progressivement les tâches amont jusqu'aux sources.

Distinctions
Backpressure ≠ buffering : le tampon absorbe temporairement une rafale ; la backpressure agit sur la source. Sans backpressure, un tampon non borné ne fait que différer la panne.
Backpressure ≠ circuit breaker : le disjoncteur coupe le flux après détection d'échecs ; la backpressure ralentit pour éviter l'échec.
Backpressure ≠ load shedding : le délestage sacrifie des messages (échantillonnage, rejet) au lieu de ralentir l'amont — choix pertinent quand la source n'est pas contrôlable (capteurs, trafic entrant).

Avantages
Bornage des ressources mémoire et CPU.
Prévention des pertes de données non intentionnelles.
Résilience face aux pics de charge.

Limites
Complexité : nécessite une coordination et une observabilité entre nœuds.
Latence : le ralentissement se propage jusqu'à la source, ce qui peut violer des contraintes temps réel.
Risques de blocage : mal conçue, elle peut provoquer des interblocages (dépendances circulaires, cycles dans le graphe de flux) ou repousser la saturation vers un point non contrôlé.
Inapplicable aux sources non ralentissables : il faut alors combiner avec du délestage ou une mise en tampon durable (log persistant).

Cas d'usage
Traitement de flux (Kafka, Flink, Spark Structured Streaming).
Microservices asynchrones via message brokers.
Systèmes temps réel et IoT, traitement audio/vidéo.

Le concept est formalisé dans le Reactive Manifesto et la spécification Reactive Streams (intégrée à Java 9 sous java.util.concurrent.Flow), et hérite directement des protocoles de contrôle de flux réseau à fenêtre (TCP).