docs: update backpressure description

This commit is contained in:
Ilkka Seppälä
2025-04-12 15:09:24 +03:00
parent 32c9031fcd
commit ce2e5f75d8
22 changed files with 77 additions and 173 deletions
+37 -102
View File
@@ -1,65 +1,46 @@
---
title: "Backpressure Pattern in Java: controlling data streams from producers to consumer inorder to prevent overwhelming the consumer"
title: "Backpressure Pattern in Java: Gracefully regulate producer-to-consumer data flow to prevent overload."
shortTitle: Backpressure
description: "Explore the Backpressure design pattern in Java with detailed examples. Learn how it helps by preventing system overload, ensuring stability and optimal performance by matching data flow to the consumers processing capability."
description: "Dive into the Backpressure design pattern in Java through practical examples, discovering how it prevents overload while ensuring stability and peak performance by aligning data flow with consumer capacity."
category: Concurrency
language: en
tag:
- Decoupling
- Asynchronous
- Event-driven
- Reactive
- Resilience
---
## Also known as
* Flow Control
* Rate Limiting Mechanism
## Intent of the Backpressure Design Pattern
The Backpressure Design Pattern is a strategy used in software systems (especially in data streaming, reactive programming, and distributed systems)
to handle situations where a fast producer overwhelms a slow consumer. The intent is to prevent system instability, resource exhaustion, or crashes by managing the flow of data between components.
Control the rate of data production so downstream consumers are not overwhelmed by excessive load.
## Detailed Explanation of Backpressure Pattern with Real-World Examples
### Real-world examples
Real-world example
#### 1. Real-Time Data Streaming (Reactive Systems)
- **Stock Market Data**
- High-frequency trading systems generate millions of price updates per second, but analytics engines can't process them all in real time.
- Backpressure mechanisms (e.g., in RxJava, Akka, Reactor) throttle or drop excess data to avoid overwhelming downstream systems.
- **IoT Sensor DataQ**
- Thousands of IoT devices (e.g., smart factories, wearables) send continuous telemetry, but cloud processing has limited capacity.
- Reactive frameworks apply backpressure to buffer, drop, or slow down data emission.
> Imagine a busy coffee shop where multiple baristas brew drinks (producers), and a single barista is responsible for carefully crafting latte art (consumer). If drinks are brewed faster than the latte-art barista can decorate them, they pile up, risking quality issues or discarded drinks. By introducing a pacing system—only sending new cups once the latte-art barista is ready—everyone stays synchronized, ensuring minimal waste and a consistently enjoyable customer experience.
#### 2. Message Queues (Kafka, RabbitMQ)
- **E-Commerce Order Processing**
- During flash sales (e.g., Black Friday), order requests spike, but payment and inventory systems cant keep up.
- Message queues like Kafka and RabbitMQ use, Limited queue sizes to drop or reject messages when full or Consumer acknowledgments to slow producers if consumers lag.
- **Log Aggregation**
- Microservices generate massive logs, but centralized logging (E.g.: ELK Stack) cant ingest them all at once.
- Kafka applies backpressure by pausing producers when consumers are slow.
In plain words
#### 3. Stream Processing (Apache Flink, Spark)
- **Social Media Trends (Twitter, TikTok)**
- Viral posts create sudden spikes in data, but trend analysis is computationally expensive.
- Backpressure in Spark Streaming prioritizes recent data and discards older, less relevant updates.
- **Fraud Detection in Banking**
- Millions of transactions flow in, but fraud detection models take time to analyze each one.
- slow down ingestion if processing lags (Throttling), save progress to recover from backpressure-induced delays (Checkpointing).
> The Backpressure design pattern is a flow control mechanism that prevents overwhelming a system by regulating data production based on the consumers processing capacity.
### In plain words
Wikipedia says
The Backpressure design pattern is a flow control mechanism that prevents overwhelming a system by regulating data production based on the consumers processing capacity.
> Back pressure (or backpressure) is the term for a resistance to the desired flow of fluid through pipes. Obstructions or tight bends create backpressure via friction loss and pressure drop. In distributed systems in particular event-driven architecture, back pressure is a technique to regulate flow of data, ensuring that components do not become overwhelmed.
### Wikipedia says
Sequence diagram
Back pressure (or backpressure) is the term for a resistance to the desired flow of fluid through pipes. Obstructions or tight bends create backpressure via friction loss and pressure drop.
In distributed systems in particular event-driven architecture, back pressure is a technique to regulate flow of data, ensuring that components do not become overwhelmed.
### Architectural Diagram
![backpressure](./etc/backpressure.png)
![Backpressure sequence diagram](./etc/backpressure-sequence-diagram.png)
## Programmatic Example of Backpressure Pattern in Java
First we will create a publisher that generates a data stream.
This publisher can generate a stream of integers.
This example demonstrates how backpressure can be implemented using Project Reactor. We begin by creating a simple publisher that emits a stream of integers, introducing a small delay to mimic a slower production rate:
```java
public class Publisher {
@@ -69,11 +50,7 @@ public class Publisher {
}
```
Then we can create a custom subscriber based on reactor BaseSubscriber.
It will take 500ms to process one item to simulate slow processing.
This subscriber will override following methods to apply backpressure on the publisher.
- hookOnSubscribe method and initially request for 10 items
- hookOnNext method which will process 5 items and request for 5 more items
Next, we define a custom subscriber by extending Reactors BaseSubscriber. It simulates slow processing by sleeping for 500ms per item. Initially, the subscriber requests ten items; for every five items processed, it requests five more:
```java
public class Subscriber extends BaseSubscriber<Integer> {
@@ -111,7 +88,7 @@ public class Subscriber extends BaseSubscriber<Integer> {
}
```
Then we can create the stream using the publisher and subscribe to that stream.
Finally, in the `main` method, we publish a range of integers and subscribe using the custom subscriber. A short sleep in the main thread allows the emission, backpressure requests, and processing to be fully observed:
```java
public static void main(String[] args) throws InterruptedException {
@@ -122,7 +99,7 @@ public static void main(String[] args) throws InterruptedException {
}
```
Program output:
Below is an example of the programs output. It shows the subscribers log entries, including when it requests more data and when each integer is processed:
```
23:09:55.746 [main] DEBUG reactor.util.Loggers -- Using Slf4j logging framework
@@ -149,73 +126,31 @@ Program output:
23:10:01.437 [parallel-8] INFO reactor.Flux.ConcatMapNoPrefetch.1 -- onComplete()
```
## When to Use the Backpressure Pattern
## When to Use the Backpressure Pattern In Java
- Producers Are Faster Than Consumers
- If a producer generates data at a much faster rate than the consumer can handle, backpressure prevents resource overload.
- Example: A server emitting events 10x faster than the client can process.
- Theres Limited Memory or Resource Capacity
- Without flow control, queues or buffers can grow indefinitely, leading to out-of-memory errors or system crashes.
- Example: Streaming large datasets into a low-memory microservice.
- Building Reactive or Event-Driven Architectures
- Reactive systems thrive on non-blocking, asynchronous flows—and backpressure is a core component of the Reactive Streams specification.
- Example: Using RxJava, Project Reactor, Akka Streams, or Node.js streams.
- Unpredictable Workloads
- If the rate of data production or consumption can vary, backpressure helps adapt dynamically.
- Example: APIs receiving unpredictable spikes in traffic.
- Need to Avoid Data Loss or Overflow
- Instead of dropping data arbitrarily, backpressure lets you control flow intentionally.
- Example: Video or audio processing pipelines where dropping frames is costly.
## When to avoid the Backpressure Pattern
- For batch processing or simple linear flows with well-matched speeds.
- If data loss is acceptable and simpler strategies like buffering or throttling are easier to manage.
- When using fire-and-forget patterns (e.g., log shipping with retries instead of slowing the producer).
* Use in Java systems where data is produced at high velocity and consumers risk overload.
* Applicable in reactive or event-driven architectures to maintain stability under varying load conditions.
## Benefits and Trade-offs of Backpressure Pattern
### Benefits:
Benefits:
- Improved System Stability
- Prevents overload by controlling data flow.
- Reduces chances of out-of-memory errors, thread exhaustion, or service crashes.
- Efficient Resource Usage
- Avoids excessive buffering and unnecessary computation.
- Enables systems to do only the work they can handle.
- Better Responsiveness
- Keeps queues short, which improves latency and throughput.
- More consistent performance under load.
- Graceful Degradation
- If the system can't keep up, it slows down cleanly rather than failing unpredictably.
- Consumers get a chance to control the pace, leading to predictable behavior.
- Fits Reactive Programming
- It's essential in Reactive Streams, RxJava, Project Reactor, and Akka Streams.
- Enables composing async streams safely and effectively.
* Protects consumers from saturation and resource exhaustion.
### Trade-offs:
Trade-offs:
- Complexity in Debugging
- Adds logic for flow control, demand signaling, and failure handling.
- More state to manage (e.g., request counts, pause/resume, buffer sizes).
- Harder Debugging & Testing
- Asynchronous flow + demand coordination = trickier to test and debug.
- Race conditions or deadlocks may occur if not handled carefully.
- Potential for Bottlenecks
- A slow consumer can throttle the entire system, even if other parts are fast.
- Needs smart handling (e.g., buffer + drop + retry strategies).
* Introduces possible delays if production must slow down to match consumer capacity.
* Requires careful orchestration in complex systems with multiple concurrent data sources.
## Related Java Design Patterns
* [Publish-Subscribe Pattern](https://github.com/sanurah/java-design-patterns/blob/master/publish-subscribe/): Pub-Sub pattern decouples producers from consumers so they can communicate without knowing about each other. Backpressure manages flow control between producer and consumer to avoid overwhelming the consumer.
* [Observer Pattern](https://github.com/sanurah/java-design-patterns/blob/master/observer/): Both involve a producer (subject/publisher) notifying consumers (observers/subscribers). Observer is synchronous & tightly coupled (observers know the subject). Pub-Sub is asynchronous & decoupled (via a message broker).
* [Mediator Pattern](https://github.com/sanurah/java-design-patterns/blob/master/mediator/): A mediator centralizes communication between components (like a message broker in Pub-Sub). Mediator focuses on reducing direct dependencies between objects. Pub-Sub focuses on broadcasting events to unknown subscribers.
* [Observer Pattern](https://java-design-patterns.com/patterns/observer/): Both patterns involve a producer notifying consumers. Observer is synchronous and tightly coupled (observers know the subject).
* [Publish-Subscribe Pattern](https://java-design-patterns.com/patterns/publish-subscribe/): Both patterns deal with asynchronous data flow and can work together to manage message distribution and consumption effectively.
## References and Credits
* [Backpressure Explained (RedHat Developers Blog)](https://developers.redhat.com/articles/backpressure-explained)
* [Hands-On Reactive Programming in Spring 5](https://amzn.to/3YuYfyO)
* [Reactive Programming with RxJava: Creating Asynchronous, Event-Based Applications](https://amzn.to/42negbf)
* [Reactive Streams in Java](https://amzn.to/3RJjUzA)
* [Reactive Streams Specification](https://www.reactive-streams.org/)
* [Reactive Programming with RxJava by Tomasz Nurkiewicz & Ben Christensen](https://www.oreilly.com/library/view/reactive-programming-with/9781491931646/)
* [RedHat Developers Blog](https://developers.redhat.com/articles/backpressure-explained)
Binary file not shown.

After

Width:  |  Height:  |  Size: 65 KiB

+26
View File
@@ -1,4 +1,30 @@
<?xml version="1.0" encoding="UTF-8"?>
<!--
This project is licensed under the MIT license. Module model-view-viewmodel is using ZK framework licensed under LGPL (see lgpl-3.0.txt).
The MIT License
Copyright © 2014-2022 Ilkka Seppälä
Permission is hereby granted, free of charge, to any person obtaining a copy
of this software and associated documentation files (the "Software"), to deal
in the Software without restriction, including without limitation the rights
to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
copies of the Software, and to permit persons to whom the Software is
furnished to do so, subject to the following conditions:
The above copyright notice and this permission notice shall be included in
all copies or substantial portions of the Software.
THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
THE SOFTWARE.
-->
<project xmlns="http://maven.apache.org/POM/4.0.0"
xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
xsi:schemaLocation="http://maven.apache.org/POM/4.0.0 http://maven.apache.org/xsd/maven-4.0.0.xsd">
@@ -30,6 +30,8 @@ import reactor.core.publisher.Flux;
/** This class is the publisher that generates the data stream. */
public class Publisher {
private Publisher() {}
/**
* On message method will trigger when the subscribed event is published.
*
-4
View File
@@ -5,11 +5,7 @@ description: "Learn how the Bloc pattern helps manage state changes in Java appl
category: Structural
language: en
tag:
- State Management
- Event-driven
- Listener Management
- Object Composition
- Dynamic Behavior
---
## Also known as
-1
View File
@@ -6,7 +6,6 @@ category: Behavioral
language: en
tag:
- Decoupling
- Architectural Style
---
## Also known as
+1 -1
View File
@@ -10,7 +10,7 @@ tag:
- Code simplification
- Decoupling
- Encapsulation
- Gang Of Four
- Gang of Four
- Interface
- Object composition
---
-5
View File
@@ -5,12 +5,7 @@ description: "Learn about the Function Composition design pattern in Java. Disco
category: Functional
language: en
tag:
- Code simplification
- Composition
- Decoupling
- Functional decomposition
- Lambda
- Reusability
---
## Also known as
+1 -4
View File
@@ -2,13 +2,10 @@
title: "MapReduce Pattern in Java"
shortTitle: MapReduce
description: "Learn the MapReduce pattern in Java with real-world examples, class diagrams, and tutorials. Understand its intent, applicability, benefits, and known uses to enhance your design pattern knowledge."
category: Performance optimization
category: Structural
language: en
tag:
- Data processing
- Code simplification
- Delegation
- Performance
---
## Also known as
+1 -1
View File
@@ -6,7 +6,7 @@ category: Behavioral
language: en
tag:
- Decoupling
- Gang Of Four
- Gang of Four
- Messaging
- Object composition
---
@@ -2,15 +2,10 @@
title: "Client-Side UI Composition Pattern: Assembling Modular UIs in Microservices Architecture"
shortTitle: Client-Side UI Composition Pattern
description: "Learn how the Client-Side UI Composition pattern allows the assembly of modular UIs on the client side, enabling independent teams to develop, deploy, and scale UI components in a microservices architecture. Discover the benefits, implementation examples, and best practices."
category: User Interface
category: Structural
language: en
tag:
- Micro Frontends
- API Gateway
- Asynchronous Data Fetching
- UI Integration
- Microservices Architecture
- Scalability
- Asynchronous
---
## **Intent of Client-Side UI Composition Design Pattern**
+1 -6
View File
@@ -2,15 +2,10 @@
title: "Microservices Distributed Tracing Pattern: Enhancing Visibility in Service Communication"
shortTitle: Distributed Tracing in Microservices
description: "Learn how the Distributed Tracing pattern enhances visibility into service communication across microservices. Discover its benefits, implementation examples, and best practices."
category: Integration
category: Structural
language: en
tag:
- Distributed tracing
- Microservices architecture
- Service communication
- Performance monitoring
- Scalability
- Observability
---
## Intent of Microservices Distributed Tracing Design Pattern
+1 -4
View File
@@ -2,13 +2,10 @@
title: "Idempotent Consumer Pattern in Java: Ensuring Reliable Message Processing"
shortTitle: Idempotent Consumer
description: "Learn about the Idempotent Consumer pattern in Java. Discover how it ensures reliable and consistent message processing, even in cases of duplicate messages."
category: Messaging
category: Structural
language: en
tag:
- Messaging
- Fault tolerance
- Event-driven
- Reliability
---
## Also known as
-8
View File
@@ -6,14 +6,6 @@ category: Behavioral
language: en
tag:
- Encapsulation
- Precision handling
- Currency safety
- Value Object
- Financial operations
- Currency
- Financial
- Immutable
- Value Object
---
## Also known as
-4
View File
@@ -6,10 +6,6 @@ category: Architectural
language: en
tag:
- Cohesion
- Simplicity
- Scalability
- Deployment
- Maintainability
---
## Monolithic-Ecommerce App
+1 -1
View File
@@ -7,7 +7,7 @@ language: en
tag:
- Decoupling
- Event-driven
- Gang Of Four
- Gang of Four
- Publish/subscribe
---
+1 -1
View File
@@ -5,7 +5,7 @@ description: "Explore the Prototype design pattern in Java with a comprehensive
category: Creational
language: en
tag:
- Gang Of Four
- Gang of Four
- Instantiation
- Object composition
- Polymorphism
+1 -1
View File
@@ -7,7 +7,7 @@ language: en
tag:
- Decoupling
- Encapsulation
- Gang Of Four
- Gang of Four
- Lazy initialization
- Proxy
- Security
-3
View File
@@ -6,9 +6,6 @@ category: Behavioral
language: en
tag:
- Decoupling
- Event-driven
- Gang Of Four
- Publish/subscribe
---
## Intent of the Publish-Subscribe Design Pattern
-3
View File
@@ -5,10 +5,7 @@ description: "Explore the Service Stub design pattern in Java using a Sentiment
category: Structural
language: en
tag:
- Testing
- Decoupling
- Dummy Services
- Dependency Injection
---
## Also known as
-6
View File
@@ -6,12 +6,6 @@ category: Structural
language: en
tag:
- Abstraction
- API design
- Code simplification
- Decoupling
- Encapsulation
- Gang Of Four
- Interface
---
## Also known as
+2 -11
View File
@@ -2,19 +2,10 @@
title: "Table Inheritance Pattern in Java: Modeling Hierarchical Data in Relational Databases"
shortTitle: Table Inheritance
description: "Explore the Table Inheritance pattern in Java with real-world examples, database schema, and tutorials. Learn how to model class hierarchies elegantly in relational databases."
category: Data Access Pattern, Structural Pattern
category: Structural
language: en
tag:
- Decoupling
- Inheritance
- Polymorphism
- Object Mapping
- Persistence
- Data Transformation
---
## Also Known As
- Class Table Inheritance
- Decoupling
---
## Intent of Table Inheritance Pattern