Rethink State

The Data-Driven World We Live In 'Data is money'—you’ve probably heard this phrase before. It’s true; data is the most valuable asset in the world today. Companies like Google, Facebook, and Amazon have built their business models around data. Applications, whether web or mobile, revolve around data: displaying it, processing it, and sending it to backends or external systems. The challenge lies in managing data efficiently to provide seamless user experiences. The ability to process and react to data in real-time is increasingly becoming a differentiator between good and great applications. As businesses continue to scale, the need for real-time data processing and event-driven architecture is becoming more evident. Developers and architects must adapt to modern methodologies that enhance application performance, scalability, and user satisfaction. A Brief History of Event-Driven Architecture Event-driven architecture (EDA) has been around for decades. It gained prominence in distributed systems, especially in enterprise software, where decoupled communication was necessary. Early implementations appeared in messaging systems, like IBM MQ and Enterprise Service Buses (ESBs), allowing applications to communicate asynchronously. With the rise of microservices and real-time applications, event-driven patterns became more popular. Modern frameworks, such as Apache Kafka, RabbitMQ, and cloud-based event buses, enable scalable event processing across various domains. In frontend development, this pattern evolved through state management libraries like Redux, RxJS, and Vuex, providing reactive and declarative approaches to UI updates. Today, event-driven principles power real-time messaging apps, collaborative tools, and even IoT ecosystems where devices react dynamically to changes in their environment. The CRUD Approach vs. Event-Driven Architecture Many web applications follow a CRUD (Create, Read, Update, Delete) approach: you fetch a resource from the backend, allow the user to modify it, and send the updated resource back. This results in UI structures built around data operations—list views, create/update forms, and delete actions. For example, if you’re building a blog, a CRUD mindset means focusing on creating, updating, and deleting posts. However, humans don’t think in terms of updating data. We use applications to accomplish tasks quickly. Wouldn’t it be more intuitive to model the application around tasks instead of data manipulations? For example, instead of manually updating post statuses, you could display a list of unpublished posts with a ‘Release’ button to quickly publish them. Event-driven architecture (EDA) shifts this paradigm by modeling actions as discrete events. Instead of thinking in terms of direct data modifications, developers focus on capturing user intents and allowing the system to react accordingly. Modeling Around Events Starting with Commands To simplify the shift in thinking, let’s introduce a small trick: separate UI interactions from UI state. Instead of directly modifying data, the UI should only dispatch commands—user intents that trigger backend logic. Consider this example of emitting an event to a global RxJS subject. import { Subject } from 'rxjs'; const GlobalEvent$ = new Subject(); class ReleasePostEvent { public readonly type = 'POST_RELEASE_COMMAND'; public readonly payload = new ReleasePostPayload(); } class ReleasePostPayload { public postId: string; } const UiComponent = ({ postId }) => { const handleReleasePost = (postId: string) => { const event = new ReleasePostEvent(); event.payload.postId = postId; GlobalEvent$.next(event); }; return handleReleasePost(postId)}>Release; }; This small shift changes how the application is structured. Instead of directly modifying the post’s status, the system captures the user's intent and acts upon it asynchronously. By decoupling state changes from UI interactions, applications gain significant performance improvements, reducing re-renders and unnecessary network requests. What Happens to These Events? This is where the magic happens: you can handle events however you like.

Feb 27, 2025 - 00:06
 0
Rethink State

The Data-Driven World We Live In

'Data is money'—you’ve probably heard this phrase before. It’s true; data is the most valuable asset in the world today. Companies like Google, Facebook, and Amazon have built their business models around data.

Applications, whether web or mobile, revolve around data: displaying it, processing it, and sending it to backends or external systems. The challenge lies in managing data efficiently to provide seamless user experiences. The ability to process and react to data in real-time is increasingly becoming a differentiator between good and great applications.

As businesses continue to scale, the need for real-time data processing and event-driven architecture is becoming more evident. Developers and architects must adapt to modern methodologies that enhance application performance, scalability, and user satisfaction.

A Brief History of Event-Driven Architecture

Event-driven architecture (EDA) has been around for decades. It gained prominence in distributed systems, especially in enterprise software, where decoupled communication was necessary. Early implementations appeared in messaging systems, like IBM MQ and Enterprise Service Buses (ESBs), allowing applications to communicate asynchronously.

With the rise of microservices and real-time applications, event-driven patterns became more popular. Modern frameworks, such as Apache Kafka, RabbitMQ, and cloud-based event buses, enable scalable event processing across various domains. In frontend development, this pattern evolved through state management libraries like Redux, RxJS, and Vuex, providing reactive and declarative approaches to UI updates.

Today, event-driven principles power real-time messaging apps, collaborative tools, and even IoT ecosystems where devices react dynamically to changes in their environment.

The CRUD Approach vs. Event-Driven Architecture

Many web applications follow a CRUD (Create, Read, Update, Delete) approach: you fetch a resource from the backend, allow the user to modify it, and send the updated resource back. This results in UI structures built around data operations—list views, create/update forms, and delete actions. For example, if you’re building a blog, a CRUD mindset means focusing on creating, updating, and deleting posts.

However, humans don’t think in terms of updating data. We use applications to accomplish tasks quickly. Wouldn’t it be more intuitive to model the application around tasks instead of data manipulations? For example, instead of manually updating post statuses, you could display a list of unpublished posts with a ‘Release’ button to quickly publish them.

Event-driven architecture (EDA) shifts this paradigm by modeling actions as discrete events. Instead of thinking in terms of direct data modifications, developers focus on capturing user intents and allowing the system to react accordingly.

Modeling Around Events

Starting with Commands

To simplify the shift in thinking, let’s introduce a small trick: separate UI interactions from UI state. Instead of directly modifying data, the UI should only dispatch commands—user intents that trigger backend logic. Consider this example of emitting an event to a global RxJS subject.

import { Subject } from 'rxjs';

const GlobalEvent$ = new Subject();

class ReleasePostEvent {
  public readonly type = 'POST_RELEASE_COMMAND';
  public readonly payload = new ReleasePostPayload();
}

class ReleasePostPayload {
  public postId: string;
}

const UiComponent = ({ postId }) => {
  const handleReleasePost = (postId: string) => {
      const event = new ReleasePostEvent();
      event.payload.postId = postId;
      GlobalEvent$.next(event);
  };

  return <button onClick={() => handleReleasePost(postId)}>Releasebutton>;
};

This small shift changes how the application is structured. Instead of directly modifying the post’s status, the system captures the user's intent and acts upon it asynchronously.

By decoupling state changes from UI interactions, applications gain significant performance improvements, reducing re-renders and unnecessary network requests.

What Happens to These Events?

This is where the magic happens: you can handle events however you like.