IET Framework
A Rust framework for building web and backend applications as one deployable program — out of modules you can reuse in the next application.
You write ordinary Rust and Cargo crates. The framework supplies the production plumbing — HTTP serving, validation, configuration, persistence, authentication, background workers — and a module pattern (contract, implementation, adapter) that keeps business rules independent of the database, user interface, and caller that happen to use them.
There is no runtime container and no service locator; the wiring lives in your composition root, where the compiler checks it.
Start the 5-minute quickstart → · Run the complete browser starter → · Read the framework architecture →
See it run
The smallest useful application is one file. This serves HTTP and shuts down cleanly on Ctrl+C:
use get;
use ;
async
async
# Terminal 1
# Terminal 2
# Hello from my application
Two framework types do the plumbing: RestApi builds an Axum router with HTTP
conventions, and HttpHost owns the listener and graceful shutdown. Everything
else is your Rust.
Follow the quickstart: create the project, run it, change it →
What the framework gives you
| I want to build | Crates | What you get |
|---|---|---|
| A JSON API | iet-http-axum | Router conventions, typed extractors, ValidatedJson, consistent problem responses |
| Server-rendered pages | iet-http-htmx-axum, iet-ui | Escaped HTML components and forms; HTMX enhances but is not required |
| Validation and errors | iet-core | One Validate trait and one AppError type, honored across layers |
| Persistent storage | iet-db, iet-db-timescale, iet-storage | Pool lifecycle, reviewed migrations, SQLx/TimescaleDB adapter, object streams |
| Sign-in and sessions | iet-auth, iet-auth-basic, session crates, integrations | Passwords, sessions (cache, database, or JWT), CSRF, revocations |
| Roles and resource access | iet-authz, iet-auth-rbac, iet-auth-acl | Deny-by-default policy ports with separately selected storage |
| Configuration | iet-config, iet-config-env | Typed, immutable settings read once at startup |
| Background work | iet-app, iet-runtime-tokio | Workers with prepare/start phases and a bounded shutdown drain |
| Caching and rate limiting | iet-cache-memory, iet-rate-limit | Typed cache and admission contracts with backend-selected scope |
| Telemetry | iet-telemetry, iet-telemetry-otel | Bounded operation names and OpenTelemetry wire-up |
The capability guides and
reference pages cover the rows above in detail. Prefer a
preset? iet-stack-web-axum and iet-stack-auth-htmx-axum compose these pieces
for you.
See it all working together
The checked-in browser starter combines sign-in, projects, tasks, search, pagination, and a database into one server-rendered app — no single-page framework:
<img src={require('@site/static/img/starter/workspace.webp').default} alt="The starter workspace with a project and its tasks" />
Run it locally in a few Docker commands: Explore the browser application →
Reuse is the point
A module is one capability with three parts: a contract that says what it
does, an implementation that says how, and an adapter that connects it to
one caller. Because the contract depends on nothing outward, the same module
runs in a web API and a command-line app unchanged — here is the checked-in
examples/reusable-notes proof:
notesthe same crate, reusedYou do not need a module split on day one. Start with one crate and promote a capability into a reusable module when a second application actually needs it. How modules fit together →
What makes this different
Ordinary Rust
No custom DSL and no generated server. If you know Rust and Axum, you already know most of the code you will write.
Reusable by construction
Contracts point at nothing outward, so the database, the UI, or the caller can be replaced without rewriting the rules between them.
One process, no hidden wiring
A modular monolith: modules call in-process, concrete types are fixed at compile time, and nothing is looked up by name on the request path.
Performance is a property of the whole application
The framework keeps dynamic dispatch out of its core ports, but it cannot make a slow query or a deployment fast. Measure your application under its real workload before claiming a performance result.
Where to go next
One endpoint on screen in about five minutes, with every command shown.
Sign-in, pages, forms, and persistence, already wired from framework modules.
From the quickstart to validated input, stored notes, and tests.
Core, features, integrations, and stacks — with the full crate catalog.
Current scope
Examples use local path dependencies from this checkout. No published release or application generator is assumed. The framework is evolving; examples are learning applications, not production-ready deployments.