Course contentsShow
← Node.js
Lesson 455 of 1,9805. Streams and BackpressureFree lesson

Stream-based Circuit Breakers

Implement a circuit breaker pattern within a stream pipeline to stop processing when upstream services fail.

In this lesson, you will learn how to protect your Node.js infrastructure by implementing a circuit breaker that halts stream processing when downstream services become unresponsive.

The Problem: Cascading Failures

When you pipe data through a long pipeline, a failing downstream service (like a database or an external API) can lead to a build-up of unhandled data. If the service is failing, retrying blindly just adds more pressure, potentially crashing your application or the target service. A Stream-based Circuit Breaker acts as a "safety fuse" inside your pipeline.

Implementing the Breaker

A circuit breaker exists in one of three states: Closed (everything is fine), Open (the service is failing; stop traffic), and Half-Open (test if the service has recovered).

In a Transform stream, you can intercept data chunks and verify the circuit state before calling the callback(). If the circuit is "Open," you shouldn't process the data; instead, you should treat the chunk as a failure or pause the pipeline.

const { Transform } = require('stream');

class CircuitBreaker extends Transform {
  constructor() {
    super({ objectMode: true });
    this.state = 'CLOSED'; // 'CLOSED', 'OPEN', 'HALF-OPEN'
    this.failureCount = 0;
  }

  _transform(chunk, encoding, callback) {
    if (this.state === 'OPEN') {
      // Reject the chunk immediately
      return callback(new Error('Circuit is open: downstream service unavailable'));
    }

    // Process and track success/failure
    try {
      // Simulate calling a downstream service
      this.push(chunk);
      this.failureCount = 0;
      callback();
    } catch (err) {
      this.failureCount++;
      if (this.failureCount > 5) this.state = 'OPEN';
      callback(err);
    }
  }
}

Why Streams Benefit

By placing this logic directly within the stream, you leverage backpressure. When the circuit breaker emits an error, the upstream source (the producer) is signaled to stop pushing data. This prevents memory bloat because you aren't buffering thousands of pending requests in an attempt to hit a broken server. The stream stops, your error handling logic triggers, and you preserve the health of the event loop.

Key Takeaway: A stream-based circuit breaker prevents system collapse by proactively closing the pipe when downstream failures cross a threshold, naturally utilizing backpressure to halt data flow.