/technology/ · How it is built
The engineering, in one place.
Cratefield is a managed service on top of Harness, an open-source Rust backend harness. This section is the technical half of the site: the request path, what a module is, every capability with the evidence behind it, and the row-by-row comparison with Supabase. None of it is required reading to use the product, and all of it is readable without an account.
Four pages
Where the detail lives.
The Module trait, the ports a module may ask for, the request lifecycle, and the security rules that ship today.
What a module is, the ones that exist, the six steps to write one, and the two ways to mount it.
Every capability with its status chip and the code or issue that backs it. The longest version of the status table.
The row-by-row comparison, the full D1 limits, and the cases where Supabase is the right answer.
The composition
One file wires the whole backend.
This is the example venture in the repository, with the comments and the mailer's arguments trimmed to fit. Each .module() is a crate. Each .runtime() call supplies an adapter for a port. .ui() is what turns the modules into pages. Swap Resend for another mailer, or the hosted runtime for a native binary, and the modules do not change.
That is the whole composition. If a module needs a port the runtime doesn't provide, this doesn't compile.
Harness::builder() .venture(Venture::new( "venture-example", "example.factory0.dev") .public_url("https://example.factory0.dev") .cors_origins(["https://example.factory0.dev"])) .module(EmailSignup::new()) .module(Waitlist::new() .products(["kontinuum", "undercover-rockstars"]) .confirm_ttl_days(7)) .templates(templates) .ui(Ui::from_spec(include_str!("../ui.json"))?) .runtime(Cloudflare::new() .db("DB") .mailer(Resend::new(..))) .build()?
The shape of it
Modules in. One binary out. A database each.
01 You pickcrates
02 We compilebuild time
.module(…)
.runtime(…)
.build()?
03 You runone db each
The same picture is the argument. What you assemble is crates, so the checks happen in cargo test rather than in production. What comes out is one binary, so there is nothing to configure at runtime. What runs is one database per backend, so a mistake cannot reach the backend next door. Per-customer databases inside one product are Designed, in epic #23. The request path, in detail.
The argument, technically
A backend you compile, not a platform you configure.
01
Modules are crates, composed at compile time.
A backend lists module crates in Cargo.toml and wires them in one file. The binary contains exactly those modules. Harness::build() refuses a module that needs a port the runtime doesn't provide, two modules claiming the same route prefix or table, or a module built against a different contract version. Misconfiguration fails cargo test, not production.
02
Portability is architectural, not a promise.
Modules never touch a vendor client, a platform binding or an environment variable. They receive trait objects and adapters answer. CI builds the example backend to wasm32 every commit: a dependency pulling tokio, mio or std::fs fails the build. MIT, not BSL.
03
Stateless by construction, at the edge.
Rust compiled to WebAssembly and served at the edge. No static mut, no thread-local outliving a request, no session store. Request scope travels in axum extensions, and the conformance kit ships the concurrent-request test that proves it.
—
Changing modules is a deploy.
Toggling a module regenerates Cargo.toml and harness.rs, rebuilds Rust to wasm and redeploys. Tens of seconds to minutes, with a build log. There is no instant config flip, and we won't draw one.
What this does not do
The limits, as numbers.
Read these before the comparison. Full version on the comparison page.
- The database is SQLite, not Postgres. No pgvector, no extensions, no LISTEN/NOTIFY.
10 GB per database, a hard cap the provider does not raise. Single-threaded: throughput tracks query duration, roughly1,000 queries/sec at 1 ms, about 10/sec at 100 ms. - No realtime and no object storage. There is no general data browser either. The admin UI renders each module's own admin views over its own tables, which is not the same thing as a console onto the database.
- The control plane does not exist yet. Not a line of it. Early access is early access.
- What to do about it. Run it on Postgres instead. The Postgres adapter and the native tokio runtime are merged, CI tests every module against both engines, and
fz data exportmoves a venture's rows from D1 into Postgres. The 10 GB cap and the single-threaded write path are D1's, not the harness's.
The code is the documentation you cannot be talked out of.