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

Stream-based Event Sourcing

Build an event-sourcing architecture where the primary data store is an immutable stream of events.

In this lesson, you will learn how to treat your application state as an evolving derivative of an immutable stream of events rather than a static database record.

The Core Concept: Events as the Source of Truth

In traditional CRUD applications, you overwrite existing state (e.g., changing balance: 100 to balance: 150). In Stream-based Event Sourcing, the state is never overwritten. Instead, the "truth" is an append-only log of events like MoneyDeposited or MoneyWithdrawn.

By processing this stream, you can derive the current state at any point in time. Because Node.js streams are naturally push-based and handle asynchronous chunks of data efficiently, they act as the perfect medium for this event log.

Building the Event Pipeline

Think of your stream as a series of facts that occurred in the past. To build your current state, you "fold" these events into a local object.

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

// Our immutable stream of past events
const eventStream = Readable.from([
  { type: 'DEPOSIT', amount: 100 },
  { type: 'DEPOSIT', amount: 50 },
  { type: 'WITHDRAW', amount: 20 }
]);

let balance = 0;

// Derive state by consuming the stream
eventStream.on('data', (event) => {
  if (event.type === 'DEPOSIT') balance += event.amount;
  if (event.type === 'WITHDRAW') balance -= event.amount;
  console.log(`Current Balance: ${balance}`);
});

Why Streams?

Using streams for this architecture offers three major advantages for your Node.js application:

  1. Replayability: If your logic changes, you can re-run the entire stream from the beginning to recreate your application state under new rules.
  2. Auditability: You have an immutable, chronological history of every change, which is essential for debugging or compliance.
  3. Backpressure: Since event logs can grow extremely large, Node.js streams allow you to process events only as fast as your application can compute the resulting state, preventing memory overflows during mass state reconstruction.

By keeping the log immutable and the state derived, you turn your database into a simple, high-performance pipe.

Key Takeaway: In Stream-based Event Sourcing, the application state is simply a summary of an immutable stream of past events, providing a perfect audit trail and the ability to reconstruct state at any point in time.