When to use tflo
tflo is not for every app. Here is how to decide.
Decision table
Start with the requirement, not the tool:
| If the requirement is… | Reach for | Reason |
|---|---|---|
| Stream plumbing, async transport, combining observables | RxJS | RxJS is the standard for async composition over arrival-ordered values. It does this well. |
| The UI is in one of N states; events drive transitions between them | XState | Finite-state machines are the right model for lifecycle orchestration and screen-state management. |
| Reactivity over current values; derived state; fine-grained re-render | JS Signals (Preact / Angular / Solid / TC39) | Signals standardize the current-value layer. They are not designed for history or time. |
| Correctness depends on event-time, absence of an event, windows, lateness, out-of-order arrival, replay, or client/server agreement on the same temporal rule | tflo | This is tflo's specific domain. The others model "now"; tflo models "what happened and when, provably." |
The honest wedge
tflo is for apps where events are timestamped and can be delayed, reordered, batched, replayed, or verified server-side. It is not for every React app. Most UI state does not need event-time correctness, and adding tflo where plain state or signals would do is unnecessary complexity.
The question to ask is: does the correctness of your logic depend on when an event happened (by the event's own clock), or on the absence of an event within a window? If yes, event-time semantics matter. If no, they do not.
Examples where event-time matters:
- A sensor heartbeat that may arrive late — "was there really no reading for 30 s, or did the packet just arrive late?"
- A multi-step user action that must complete within a deadline measured from the first event, not from when the server noticed.
- Client-side fraud signals that must agree with the server after the fact, even if the client was offline.
- Backtesting a rule against historical data — the rule must produce the same output as it would have live.
Compose, don't replace
These tools are not competitors. A well-structured app may use all four:
- RxJS Transport and stream composition — get the events from source to consumer.
- XState Screen lifecycle — "loading", "idle", "error", transitions on user events.
- JS Signals Reactivity — hold the latest tflo verdict for rendering; propagate changes without re-render.
- tflo Event-time correctness — evaluate the temporal rule over the timestamped event log; emit a typed verdict.
Each does what it is good at. tflo produces a verdict; a Signal holds it for rendering; XState transitions the screen on it; RxJS delivered the raw events in the first place.
Comparison set by audience
The relevant comparison set shifts with the reader's context. This is expected and correct.
Frontend / React readers naturally compare tflo to RxJS, XState, and JS Signals — the tools they reach for when state or events get complex. The table above addresses that comparison directly.
Streaming / backend readers will reach for Apache Flink, Esper, Kafka Streams, or timely-dataflow as reference points. tflo is a composable alternative in that space — a pure, embeddable engine rather than a distributed system or a JVM-based runtime. It does not replace a Kafka cluster; it can run as a processing stage inside one.
Position tflo in either context as an alternative and a composable layer, not as a head-to-head feature winner. Every tool in the comparison set exists because it solved a real problem well.
Next: Mental model — a precise side-by-side of how each tool models time — or Event-time vs processing-time for the foundational distinction that drives tflo's design.