noex ecosystem

noex-store

Schema-driven Reactive Store

In-memory store with automatic schema validation, Convex-style reactive queries, ACID transactions, and pluggable persistence. Built on noex GenServer primitives for fault-tolerant data management.

Key Features

Everything you need for reactive data management in Node.js

Schema & Validation

Define typed bucket schemas with constraints, auto-generated fields, unique indexes, and format validators. Records are validated automatically on every write.

Reactive Queries

Convex-style dependency tracking re-evaluates queries automatically when underlying data changes. Record-level and bucket-level granularity with deep-equality diffing.

ACID Transactions

Atomic multi-bucket writes with optimistic locking. Read-your-own-writes within a transaction, automatic rollback on conflict, and events published only after commit.

Pluggable Persistence

Swap between File, SQLite, or Memory adapters. Debounced batching keeps writes efficient. Per-bucket opt-out for ephemeral data.

TTL & Size Limits

Per-record TTL with human-readable durations and automatic purging. Max-size eviction removes oldest records when a bucket exceeds capacity.

Event System

Wildcard pub/sub on bucket mutations. Subscribe to specific buckets, event types, or all changes with a single pattern. Powers reactive queries and persistence under the hood.

Supervision Architecture

One GenServer per bucket, supervised with one-for-one strategy. If a bucket crashes, others keep running.

Store
Supervisor (one_for_one)
BucketServer × N
QueryManager
EventBus
TtlManager
Persistence

Each bucket runs in its own GenServer — full process isolation, sequential message processing, no race conditions.

QueryManager subscribes to EventBus for change notifications. Persistence debounces writes via EventBus. All coordination is event-driven.

See It in Action

Real code examples showing schema definition, reactive queries, and transactions

schema.ts
import { Store } from '@hamicek/noex-store';

const store = await Store.start();

await store.defineBucket('users', {
  key: 'id',
  schema: {
    id:    { type: 'string', generated: 'uuid' },
    name:  { type: 'string', required: true },
    email: { type: 'string', format: 'email', unique: true },
    role:  { type: 'string', enum: ['admin', 'user'], default: 'user' },
  },
});

const users = store.bucket('users');

// Insert — validated against schema, id auto-generated
const alice = await users.insert({
  name: 'Alice',
  email: '[email protected]',
});

// Read
const user = await users.get(alice.id);

// Update
await users.update(alice.id, { role: 'admin' });

// Query
const admins = await users.where({ role: 'admin' });

How It Compares

noex-store vs popular reactive stores and client-side databases

Featurenoex-storeRxDBTinyBaseSignalDBLokiJSDexie.jsWatermelonDB
Reactive QueriesConvex-styleRxJS ObservablesQuery engineSignal-basedDynamicViewsliveQueryobserve()
Schema ValidationBuilt-in DSLJSON SchemaSchematizersValidate eventColumn types
Multi-collection TransactionsOptimistic lockingSingle-storeSingle-coll.ACIDWriter blocks
PersistenceAdapter-basedSwappable storageAdaptersAdaptersAdaptersIndexedDBSQLite
TTL / Auto-expirationFirst-classCleanup onlyBuggy
Event Bus with WildcardsTopic pub/subRxJS streamsGranular listenersCollection eventsCollection eventsHooksObservables
In-memory First
Supervision TreeOTP one_for_one
Secondary IndexesUnique + non-uniqueJSON SchemaIndexes APIQuery selectorsUnique + binaryCore featureisIndexed
Bundle Size (gzip)~5 kB60–150+ kB3.5–8 kB~5–8 kB~20 kB~26 kB~2 MB
StatusActiveActive (freemium)ActiveActiveArchivedActiveActive

What Makes noex-store Unique

Supervision Tree

Each bucket is an isolated GenServer actor. If one crashes, the supervisor restarts it while siblings continue unaffected.

First-class TTL

Declarative per-bucket expiration with automatic background purge and _expiresAt metadata.

Convex-style Reactive Queries

Plain async functions become live subscriptions with automatic bucket-level and record-level dependency tracking.

Multi-bucket ACID Transactions

Version-based optimistic locking with atomic commit and best-effort rollback across collections.

Wildcard Event Bus

Subscribe to patterns like bucket.*.deleted or bucket.users.* across the entire store.

Start building reactive data layers

Add noex-store to your project in seconds

npm install @hamicek/noex-store
$ npm install @hamicek/noex-store

Support the Project

Love noex? Help us keep building amazing tools

Bitcoin
Bitcoin QR Code