FlatSignals is an ultra-fast reactivity library (~0.5 KB) optimized for high-frequency, few-to-many updates.
- No graph traversals
- O(1) dynamic dependency management
- Lazy computations by default
Note: Benchmarks were run in a controlled environment. Results may vary based on hardware and JavaScript engine. You can reproduce these benchmarks by cloning the repo and running
pnpm bench.
| Library | Operations/sec ⚡ | vs flatsignals |
|---|---|---|
| flatsignals 🏆 | 449,848 | baseline |
| alien-signals | 261,082 | 1.72x slower |
| @preact/signals | 230,899 | 1.95x slower |
| @reactively/core | 182,403 | 2.47x slower |
| @vue/reactivity | 152,709 | 2.95x slower |
| @maverick-js/signals | 137,712 | 3.27x slower |
| Angular Signals | 98,597 | 4.56x slower |
| @solidjs/signals | 78,849 | 5.71x slower |
| Library | Operations/sec ⚡ | vs flatsignals |
|---|---|---|
| flatsignals 🏆 | 976,139 | baseline |
| alien-signals | 502,513 | 1.94x slower |
| @preact/signals | 492,543 | 1.98x slower |
| @reactively/core | 438,882 | 2.22x slower |
| @maverick-js/signals | 343,368 | 2.84x slower |
| Angular Signals | 241,189 | 4.05x slower |
| @vue/reactivity | 221,537 | 4.41x slower |
| @solidjs/signals | 202,492 | 4.82x slower |
| Library | Operations/sec ⚡ | vs flatsignals |
|---|---|---|
| flatsignals 🏆 | 4,556,987 | baseline |
| alien-signals | 3,028,320 | 1.50x slower |
| @preact/signals | 2,531,788 | 1.80x slower |
| @reactively/core | 1,688,053 | 2.70x slower |
| Angular Signals | 1,614,432 | 2.82x slower |
| @vue/reactivity | 1,563,865 | 2.91x slower |
| @maverick-js/signals | 1,407,975 | 3.24x slower |
| @solidjs/signals | 870,080 | 5.24x slower |
# npm
npm install flatsignals
# pnpm
pnpm add flatsignals
# yarn
yarn add flatsignalsimport { signal, computed, effect } from "flatsignals";
const counter = signal(0);
const double = computed(() => counter.val * 2);
const log = effect(() => console.log(double.val));import { useFlatSignal, useFlatReader } from "flatsignals/react";
import { counter, double } from "./signals";
function MyCounter() {
const [val, setVal] = useFlatSignal(counter);
return <button onClick={() => setVal(val + 1)}>Count: {val}</button>;
}
function ReadDouble() {
const val = useFlatReader(double);
return <div>{val}</div>;
}Best suited for: Scenarios with a small number of reactive signals driving many dependent computations.
Limitations:
- Signal limit: Maximum of 32 signals per root. Beyond this limit, effects may trigger even when their tracked signals haven't changed.
- Set complexity: O(N) time proportional to dependent computations (amortized through batching)
- Eager propagation: All downstream nodes marked dirty immediately, even when intermediate values unchanged