zino: a spec-driven Rust framework where a schema drives the whole application
Spec-driven framework for composable applications in Rust.
At a glance
- What is it?
- zino is a strongly opinionated Rust framework for composable applications, built around a specification layer that generates the database schema, the OpenAPI document and the service code from one definition. It suits a team that wants one source of truth for an API service, and the split into eleven crates is the thing to understand before you start.
- Who is it for?
- zino fits a team building an API service where the schema, the documentation and the code would otherwise drift apart, because the spec layer is what ties them together, and because the ORM and the OpenAPI generator are built on top of it rather than beside it.
- Can I use it commercially?
- Yes. MIT is a permissive licence: you can use, modify and sell software built on it, as long as you keep its copyright and licence notices.
- Is it still maintained?
- Yes. The repository last received commits 9 days ago.
- What is it written in?
- Mainly Rust, according to GitHub's language statistics.
Answers come from the project's GitHub data, last synced on October 23, 2026, and from our analysis. They are not legal advice.
Editorial analysis
Spec-driven means one definition, several outputs
zino is a spec-driven strongly opinionated framework for composable applications in Rust which emphasizes simplicity, extensibility and productivity.
The adjective spec-driven is the whole thing, and it is a different way of organising an application than the usual Rust one. Instead of hand writing a struct, a migration, a handler and an OpenAPI annotation, you describe the shape once in a specification and the framework derives the rest.
The feature list spells out the pieces, and three of them are the ones that follow from a spec layer. Adopt an API-first approach to development with open standards. Expressive ORM for MySQL, PostgreSQL and SQLite based on sqlx. And innovations on query population, field translation and model hooks.
Those last three are worth pausing on, because they are the mechanisms that make a spec layer more than a code generator. Query population is the inverse of the usual problem, where the framework can populate a response object from a query result instead of requiring you to map field by field. Field translation is the rename and conversion layer between a database column, an API field and a language type. Model hooks are the lifecycle callbacks, the before and after of a create or an update, which is where the things that are hard in an ORM live.
The rest of the list is the standard web framework set, and it is a good sign that it is short. Out-of-the-box features for rapid application development. Minimal design, composable architecture and high-level abstractions. Practical conventions to get the best performance. Built-in support for tracing, metrics and logging. And full integrations with actix-web, axum, dioxus and more.
The three integrations matter because they are the ones that decide the shape of your application. zino sits above the web framework rather than replacing it, so a service can be an actix app, an axum app or a dioxus desktop app, and the specification and the data layer stay the same. The topics confirm the orientation: asynchronous, http, orm, rust, web.
The documentation points at a DeepWiki page for the project rather than a conventional docs site, and each crate is published separately on crates.io with its own docs.rs page, so you can read only the parts you use.
Eleven crates, and a running example in three lines
The crate list is the architecture, and it is worth reading before you add the dependency.
`zino-core` holds the core types and traits, and it is the crate everything else builds on. `zino-auth` is authentication and authorization. `zino-channel` is cloud events and subscriptions. `zino-storage` is files and storage services. `zino-http` is requests and responses. `zino-openapi` is the OpenAPI documentation generator. `zino-orm` is the database schema and the ORM. `zino-derive` is the derived traits, so the proc macros. And then `zino-actix`, `zino-axum` and `zino-dioxus` are the integrations with the three web stacks.
That is eleven crates in the workspace, and the split tells you what the framework considers separable. The data layer, the HTTP layer, the auth layer, the event layer and the storage layer are all independent of the web framework, so you can adopt the ORM without adopting the HTTP abstractions, or take the spec layer with only the pieces you need.
The getting started path is unusually short. You start with the example actix-app, axum-app or dioxus-desktop, and it requires Rust 1.95 or later to build the project:
cd examples/axum-app
cargo runThe Cargo manifest for a new application is also short, with the feature flag naming the integration you want:
[package]
name = "zino-app"
version = "0.1.0"
edition = "2024"
rust-version = "1.95"
[dependencies]
zino = { version = "0.46", features = ["axum"] }And the application itself is three lines, with a prelude import and a boot and run:
use zino::prelude::*;
fn main() {
zino::Cluster::boot().run()
}The word Cluster in that one line is a hint about the shape of the thing, since it implies the application is composed of a cluster of services rather than being a single object graph. That is consistent with the composable architecture claim and with the fact that there is a `zino-channel` crate for cloud events and subscriptions, which is how separate processes in that cluster talk to each other.
There is also a minimal-app example alongside the three framework ones, and the examples directory has its own Cargo.toml, so the examples are a workspace of their own.
The dependency list tells you what is actually used
The workspace dependencies are declared once and shared, and reading them is a good way to understand the framework's technical choices.
The async runtime is tokio at 1.53.2 with the macros, net, rt-multi-thread, signal, time and parking_lot features. The HTTP stack is the `http` crate at 1.5.0 rather than a framework type, with `reqwest` at 0.13.5 with gzip, json and multipart for outbound calls, and `reqwest` configured with default features disabled, which is a deliberate choice to keep the transitive dependency set small.
The database is sqlx at 0.8.6 with the chrono, json, rust_decimal and uuid features. The ORM is built on it, and the choice of sqlx is significant, since sqlx is a compile-time checked query layer rather than a runtime one, which moves SQL errors from runtime to compile time.
For numbers there is `rust_decimal` at 1.43.0, which is the decimal arithmetic library rather than binary floating point, and the framework enables it on sqlx, so money and other exact values do not go through an f64. The `percent-encoding`, `mime_guess` and `url` crates cover the HTTP plumbing.
Serialization is serde with derive, and serde_json with the `raw_value` feature, which is the option that lets you hold a partially parsed JSON document. There is `serde_qs` for query string parsing, `toml` for configuration, `chrono` for date and time with serde, and `regex` at 1.13.1 for pattern matching. `smallvec` is there for the cases where a small inline vector beats a heap allocation, and `ahash` is the hasher.
Two entries in that list are unusual and worth a look. `sm3` is the Chinese cryptographic hash standard, and `hmac` is there for signing. The `jwt-simple` dependency is configured with default features off and the `pure-rust` feature on, which is the same idea as the reqwest configuration: keep the cryptography pure Rust so the build does not need a C toolchain, which matters for the people building on a different platform or in a container.
`fluent` at 0.17.0 is Mozilla's localisation system, and `unic-langid` is the language identifier it works with, so internationalisation is in the dependency set rather than being an afterthought. `apache-avro` is there for Avro, which pairs with the cloud events work in zino-channel.
And `convert_case` at 0.12.0 is the crate that does case conversion between snake_case, camelCase and PascalCase, which is the mechanism behind field translation between the database column name, the API field name and the Rust type name.
The `metrics` crate at 0.24.6 and `tracing` at 0.1.44 are the observability pair, and the README lists them as built-in support for tracing, metrics and logging.
Where a spec-driven framework earns its keep and where it fights you
The honest case for this approach, and the honest case against it, both follow from the spec layer being the centre of the design.
The case for is about drift. In a hand written service, the struct, the migration, the validation and the OpenAPI schema are four artefacts that have to agree, and nothing enforces that they do. In a spec driven one, the schema is derived, so it cannot disagree with itself. For a team that has been bitten by an API that documents a field the server stopped returning, that is a real class of bug removed rather than a feature added.
The case against is that the spec becomes the place where all the expressiveness has to fit. Anything the schema language cannot express is a place where you leave the framework and write code by hand, and a framework that is strongly opinionated makes those exits expensive. A conditional field, a computed aggregate, a query with a shape the ORM does not model, and each one is a fight.
The third consideration is the layer count. There is a spec, and there are traits, and there are derived traits, and there is an ORM on top of sqlx, and there is a cluster abstraction, and there is a web framework underneath. Each layer is sensible and the sum is a lot of concepts to hold before you write your first handler. A team that has used axum plus sqlx directly will feel that, and the framework's own answer to it is the minimal-app example.
The fourth is the version cadence. The workspace is at 0.43.0 with releases at 0.41.0 in December 2025, 0.42.0 in January 2026 and 0.43.0 in March 2026, which is a monthly or better rhythm, and the getting started example depends on zino 0.46, which is a different number from the released version. So the example is tracking a version ahead of the last tag, and if you follow the example you are on a version that the documentation and the release history describe differently. Worth checking which one you are actually pinning.
Where the framework clearly wins is a team that has already decided it wants an API service with a database, an OpenAPI document and conventional structure, and that would otherwise spend its first two weeks writing the scaffolding. It loses to a thin layer when the application has one unusual shape, because then the spec language is a tax on the one part of the system that is genuinely custom.
Editorial conclusion
zino fits a team building an API service where the schema, the documentation and the code would otherwise drift apart, because the spec layer is what ties them together, and because the ORM and the OpenAPI generator are built on top of it rather than beside it. Skip it if you want a thin layer over axum or actix with your own conventions, since the framework is strongly opinionated and the opinions are the point, and note the version numbers, where the workspace is at 0.43.0 with the getting started example depending on zino 0.46, so pin carefully. Before you commit, read the crates table and work out which of the eleven you actually need, because the crate split is a deliberate design and not an accident. The last push was on 2026-10-14.
Frequently asked questions
What is zino?
It is a spec-driven, strongly opinionated framework for composable applications in Rust, emphasising simplicity, extensibility and productivity, with out-of-the-box features, an API-first approach using open standards, an ORM over sqlx, and built-in tracing, metrics and logging.
Which crates does the zino workspace contain?
zino-core for core types and traits, zino-auth for authentication and authorization, zino-channel for cloud events and subscriptions, zino-storage for files and storage services, zino-http for requests and responses, zino-openapi as the documentation generator, zino-orm for the database schema and ORM, zino-derive for derived traits, and zino-actix, zino-axum and zino-dioxus as the framework integrations.
How do I start a zino application?
Start from one of the examples, actix-app, axum-app or dioxus-desktop, with `cd examples/axum-app` and `cargo run`. It requires Rust 1.95 or later, and the dependency is added as `zino = { version = "0.46", features = ["axum"] }` with a boot and run of `zino::Cluster::boot().run()`.
Which databases does the zino ORM support?
MySQL, PostgreSQL and SQLite, with the ORM built on sqlx at 0.8.6 configured with the chrono, json, rust_decimal and uuid features, and rust_decimal enabled so exact values do not pass through binary floating point.
What is the maintenance state of zino?
The workspace is at 0.43.0 with releases 0.41.0 in December 2025, 0.42.0 in January 2026 and 0.43.0 in March 2026, while the getting started example depends on zino 0.46, so check which version you are pinning. The last push was on 2026-10-14 and the licence is MIT.
Official sources
Add this badge to your README
If you maintain this project, the badge below links readers to this analysis and shows its maintenance status from the daily GitHub snapshot. Paste the markdown into your README; add ?metric=license or ?metric=stars to the image URL for a different field.
[](https://hysenlabs.com/projects/zino-rs-zino)Was this useful?