Eigen compiles your application into one static binary and keeps every kind of state in one Postgres. The binary is your web app, your desktop app, your phone app, and your API. Postgres is your database, your job queue, your cron scheduler, your sync log, your transaction engine — and your complete history. The framework supplies everything in between — the sync engine, the reactive UI layer, the workflow engine, the component library — as code inside the binary, not services beside it. Two things, and you can point at both of them.
For a decade, application architecture has forced a choice of religion: effortless server-driven reactivity, or offline-capable client-owned data. The frameworks that give you one are philosophically incapable of the other.
One rule makes it work: rendering never crosses the network — only data does. Whatever binary is closest to the screen renders, against whatever database is closest to it. Connectivity becomes a property of the sync engine, not a mode you write.
Public listener. Serves the hypermedia plane to browsers and the data plane to native peers and integrations. Postgres behind it.
The same handlers render into a Tauri 2 shell against a local SQLite replica that syncs in the background. Tauri already ships desktop, iOS, and Android — eigen doesn't build shells, it inhabits them, bound to loopback.
Not a mode — a circumstance, and on a phone it's a daily one: the basement, the job site, the plane. Mutations queue, remote changes apply on reconnect. No spinner, because the database never left the device.
Every guarantee in this document has to know your schema: sync needs the horizon, the vault needs the PII fields, history needs the tables, forms need the types, policy needs the scope. So eigen has one source of truth: the resource — a declaration the whole framework derives from, the idea Ash proved on the BEAM, translated to Rust's terms.
From one resource! block, cargo eigen derives the SQL schema and its migrations, the history tables, the sync horizon, the intent endpoints and their policy checks, the form components — and the invariants that bind them. In Rust the verifier layer is mostly the compiler: a hallucinated field doesn't need a linter; it doesn't compile. Cross-resource invariants run in cargo eigen check.
Deliberately a closed derivation pipeline, not a meta-framework: a fixed set of derivations done deeply, not an open extension system. That's the honest Rust translation of Ash — and the reason one person can maintain it.
Handlers never emit markup. They emit typed semantic components — and because the tree is typed, eigen does at compile time what LiveView does on the BEAM: split every component into static parts (sent once) and dynamic bindings (tracked). When deal.stage changes, the patch on the wire is a few bytes, not a re-rendered fragment. Rust doesn't have this today; eigen is where it gets built.
Eigen owns the patch protocol end to end. The v1 client runtime is the vendored Datastar client — MIT, ~15 KB, pinned, shipped from the binary, audited once — replaced by eigen's own smaller runtime once production usage has written the real spec. Owning both ends of the wire makes the dependency a file in the repo, not a vendor.
And the runtime is latency-adaptive — the one thing no generic library will ever ship. On loopback, round trips are free and optimistic UI machinery simply turns off. Over WAN, local-echo signals cover the gap. Same components, same protocol, tuned to how far away “the server” happens to be.
Eigen ships a standard vocabulary — roughly twenty-five semantic components: page, nav, form, field, table, list, card, dialog, badge, and kin — headless, themed by CSS variables, composed into your own components freely. This is not a styling opinion; it's load-bearing architecture. The future native renderers can only reconcile a vocabulary they know. A closed, versioned component set is what makes “same handlers, native widgets later” a promise instead of a hope.
The vocabulary compounds with the resource: form(deal) derives its fields from the declaration — types drive inputs, constraints drive validation, and a Pii<> field renders masked automatically, because the component knows what the schema knows. The escape hatch is honest: raw HTML is allowed anywhere, and marks that subtree HTML-only — visibly opting it out of the native lane, a trade you make on purpose, per subtree, never by accident.
Sync engines are company-sized because they bolt onto arbitrary schemas they don't control — generic replication decoding, bucket abstractions, their own storage. Eigen owns the schema, and eigen already keeps history — every version of every row, sequenced. The change stream isn't a new subsystem; it's an indexed query against the history tier. One table, three features: audit, time travel, sync.
The replica is a projection, not a peer. Down: cursor-based delta pulls, each batch applied in one SQLite transaction. Up: durable intents — the same form submit, queued, intent ID = workflow ID, so retries are no-ops. The device never merges; the server replays intents in order, policy decides, and a rejected intent comes back as UI, not a silent conflict.
Horizons are membership tables (org, assignment, territory) — not arbitrary predicates — so revoking access naturally emits delete markers into the stream: the hardest problem in partial replication becomes ordinary rows. And the v1 rule a general engine can't afford: when in doubt, resnapshot. Replicas hold a working set, not a warehouse.
A workflow is ordinary code, checkpointed step-by-step in Postgres — the durable-execution pattern DBOS proved, implemented natively in eigen. Crash, redeploy, or kill the process — on restart it resumes from the last completed step. Steps that touch the database commit their effect and their checkpoint in one transaction: exactly-once, guaranteed by Postgres itself.
No orchestrator cluster. No Temporal server on the critical path. Durable execution is a library inside the binary — checkpoints are just rows.
And because enqueueing a workflow is a database write — and eigen already syncs database writes — a follow-up scheduled offline at 30,000 feet lands in the queue when you do. Devices enqueue; servers execute. A step with real-world effects only ever runs where the truth lives.
Every box below is a thing most stacks deploy, version, secure, monitor, and pay for. In eigen, each one is a table, a query, or a library call — inside the two things you already have.
→ postgres — caching is a solved read; state was never Redis's job
→ postgres — LISTEN/NOTIFY and durable queues, transactional with your data
→ the binary — durable execution is a library, not a Temporal deployment
→ postgres — scheduled workflows are delayed rows
→ the binary — every server node is already a worker
→ workflows — delivery is a step; steps retry and checkpoint
→ the binary — the history tier is the sync log; the loop ships inside
→ postgres — partitioned history + framework-refreshed rollups; dashboards read summaries
→ postgres — identity is a core resource: orgs, users, roles, sessions, policy
→ the binary — typed components diffed server-side; a vendored ~15 KB runtime applies patches
→ gone — no bundler, no node_modules, no second deployable drifting out of sync
→ the resource — schema, queries, forms, and policy derive from one declaration
The routing rule isn't hot-versus-cold storage — it's read intent. A live page asks “what's true right now, and let me change it”: a point read and a write, against indexed rows. A report asks “what happened, over time”: a scan, against partitioned history tables and framework-refreshed rollups in the same Postgres. Dashboards read the small summary, never the raw stream.
Most databases are amnesiac by construction: every UPDATE overwrites the evidence. Eigen never runs a destructive update against truth — the change stream keeps every version of every row, time-partitioned, in the database you already run. So “as of” stops being a forensic project and becomes a WHERE clause — and the same rows are the sync log the replicas pull from. Audit, undo, as-reported reporting, and offline sync aren't four systems. They're one tier, read four ways.
An immutable history and “delete my data” look like a contradiction. Eigen resolves it in the schema: a Pii<> field never enters the history stream — it lives in a mutable, keyed vault in Postgres; everything downstream carries only the key reference. And because the sync log is the history stream, the protocol is structurally incapable of shipping PII to a device — not filtered out; never present.
Online, actuals stream from the vault at render time and are never written to the replica; offline, the same field — the same derived form component — renders its abstraction: a label and ••••. The field tech in the dead zone sees the job, the schedule, the notes. The customer's phone number was never on the phone.
Erasure means destroying the key — crypto-shredding. History still replays perfectly; personal values come back null. And because no device ever persisted plaintext, erasure has no stragglers in the field. GDPR-compliant event sourcing goes from oxymoron to checkbox.
This binary is a long-lived daemon on your customers' hardware, holding their business data, parsing input from the network, for years between updates. In an unsafe language that is a CVE surface; in safe Rust the whole bug class is gone — an answer a B2B security questionnaire accepts. No GC, so no pauses under ten thousand open SSE streams.
Rust also supplies the two machines eigen is built from: proc macros — the compile-time metaprogramming that makes the resource derivation pipeline and the static/dynamic component split possible, with the compiler itself as the first verifier — and a mature crate floor: tokio + axum on the server plane, sqlx against Postgres, rusqlite over the replica, serde at every boundary, Tauri 2 as the shipped shell on desktop, iOS, and Android. The runtime dependency surface is your binary and Postgres. Everything else is a build-time artifact you pin, audit, and own.
A single well-provisioned Postgres sustains tens of thousands of workflow steps per second. The median SaaS never sees one percent of that. Vertical SaaS, B2B platforms, internal tools, ops software — and above all the field teams that lose signal daily and get told “offline is on the roadmap” by every vendor they evaluate. This architecture covers the overwhelming majority of software businesses with two deployed things and one on-call runbook.
Scale up by buying a bigger Postgres — the most boring, best-understood move in the industry. Scale out by adding identical stateless binaries. You will exit this envelope around the time you can afford a platform team to build the next one.
Desktop, iOS, and Android shells — shipped, stable, someone else's roadmap. Eigen binds to loopback inside them; the shell workstream is deleted.
The server plane, both databases, every boundary — the most exercised crates in the ecosystem.
Logical sequencing, LISTEN/NOTIFY, partitioning, transactional DDL — the sync log, live channel, and history tier are queries, not services.
MIT, ~15 KB, pinned and shipped from the binary — the v1 patch applier. Replaced by eigen's own runtime once production usage writes the spec. A file in the repo, not a vendor.
The resource-derivation idea, the static/dynamic diff split, and durable execution over Postgres tables — proven elsewhere, implemented natively here. Credits, not dependencies.
resource! + cargo eigen: schema, migrations, history, horizons, intents, policy, forms — one declaration, a closed set of derivations, the compiler as first verifier.
Typed component tree, compile-time static/dynamic tracking, byte-sized patches, an owned wire protocol, latency-adaptive delivery. LiveView's crown jewel, transplanted to Rust.
~25 semantic, headless, themeable components — closed and versioned because the native lane requires it; forms derived from resources, PII masked by construction.
History-native deltas down, durable intents up, membership horizons, resnapshot as the correctness escape hatch. Small because the schema is owned — the flagship, not the 70%.
Checkpoints as rows, effect + checkpoint in one transaction, queues and cron as delayed rows — devices enqueue, servers execute.
Crypto-shredding as a schema primitive; actuals render server-fed and never persist on a device — masked is what offline looks like.
Orgs, users, roles, sessions — not a bundled app, but the resources horizons, policy, and the vault are structurally built on. The only scope the framework ships.