Cornucopia compiles your PostgreSQL queries into a Rust crate
Generate type-checked Rust from your PostgreSQL.
At a glance
- What is it?
- Cornucopia prepares your SQL against a real PostgreSQL database, validates it, and generates a separate Rust crate with typed interfaces to those queries. The approach is deliberately SQL-first, with no ORM in the middle, and version 1.0 absorbed the Clorinde fork with a rewritten code generator.
- Who is it for?
- Cornucopia suits a Rust team that already writes plain SQL against PostgreSQL and wants the database to be the source of truth for types, without giving up raw queries for an ORM or a query builder.
- Can I use it commercially?
- Yes. Apache-2.0 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 2 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 22, 2026, and from our analysis. They are not legal advice.
Editorial analysis
Queries are prepared against a real database, then compiled
The central idea of Cornucopia is that a Rust type should come from a query that PostgreSQL itself accepted. The project generates type-checked Rust interfaces from PostgreSQL queries, with an emphasis on compile-time safety and high performance, and it works by preparing your queries against an actual database and then running an extensive validation suite on them. Rust code is then generated into a separate crate, which can be imported and used in your project.
That last detail is the one that decides the workflow. The generated code is not a module inside your project, it is a crate with its own manifest, and you depend on it by path:
cornucopia = { path = "./cornucopia" }A separate crate has a real consequence. The types of your database access layer live in their own compilation unit, so a schema change that alters a result type breaks the build of that crate, and the compiler points at the generated code and the query that caused it. It also means the generated crate can be published or reused across several binaries without regenerating it into each one.
The dependency list in the project manifest explains the mechanism. tokio-postgres and postgres-types are the database interface, so the generated code speaks to the same driver the ecosystem already uses. chumsky is listed as the parser, which is how the SQL annotations are understood. quote, proc-macro2, syn and prettyplease are the code generation toolchain, with prettyplease doing the formatting so the output looks hand written. miette with the fancy feature provides the diagnostics, and the project advertises catching SQL errors at compile time with powerful diagnostics as its headline feature. clap handles the command line, heck handles word case, and dotenvy means the database connection can come from an environment file.
SQL first: a comment names the query, colons name the parameters
The query language is plain PostgreSQL with a small annotation convention added, and the project is emphatic that this is not an ORM or a query builder, just the SQL you already know. A query file carries a comment line that names the query, and named parameters are written with a colon:
-- queries/authors.sql
--! insert_author
INSERT INTO authors
(first_name, last_name, country)
VALUES
(:first_name, :last_name, :country);
--! authors
SELECT first_name, last_name, country FROM authors;The named parameters are what make the generated function usable, because the Rust function takes one argument per parameter with the type PostgreSQL inferred, rather than a positional list of mixed types. The comment line gives the function its name, so the file layout on disk and the module layout in Rust line up.
The generated API follows from that. In the example, the queries module exposes an authors function and an insert_author function, and each one is a builder you bind parameters to, then execute:
use cornucopia::queries::authors::{authors, insert_author};
insert_author()
.bind(&mut client, &"Agatha", &"Christie", &"England")
.unwrap();
let all_authors = authors().bind(&mut client).all().unwrap();The bind step is where the type safety lands. A parameter of the wrong Rust type, or a missing parameter, is a compile error rather than a runtime failure at the database. The all() call returns the full result set, and the row struct exposes the selected columns as fields, which is the practical payoff of the whole exercise: the shape of a result is known to the compiler without a query builder ever being involved.
Installing the generator and adding the crate to your project
The generator is an ordinary Rust binary, installed with cargo:
cargo install cornucopiaAfter that the flow is the three step cycle the project describes. You write your PostgreSQL queries. You use Cornucopia to generate a crate with type-safe interfaces to those queries. You import and use the generated code in your project.
The part worth planning for is the middle step, because it needs a database. Preparing a query means sending it to PostgreSQL and letting the server describe the result, so the generator needs a live connection to a database whose schema matches what your queries expect. In practice that means a development database with the same migrations applied as production, and a regeneration step in your build or deploy pipeline whenever a query or a migration changes.
Two supporting details come from the project setup. The presence of dotenvy in the dependency list means the connection parameters can be supplied through an environment file, which is how the examples and the test suite point the generator at a local instance. And the repository carries an auto_build example alongside the basic ones, which is the case where regeneration is wired into the build rather than run by hand, and it is the example to read if you want the crate to stay in step with the schema automatically.
The documentation is a book, and the project points to a quickstart through the examples directory as the faster route for a first run.
Sync, async, WebAssembly and custom Rust types
The feature list is short, and each entry answers a question a Rust developer actually asks.
Type safety is the reason to use the tool. SQL-first is the design commitment: plain queries in, generated Rust out. Fast is stated as performance close to hand-written rust-postgres code, and the project backs that with a benchmark suite: the manifest defines an execution benchmark and a codegen benchmark, and the dev dependencies include postgres, diesel and sqlx, so the execution numbers are measured against other Rust database approaches rather than asserted.
Flexible covers the two things Rust teams argue about. The project states that it works with sync and async code and with connection pools, and the examples directory shows the variants: basic_sync, basic_async, basic_async_wasm and custom_types, plus auto_build. The WebAssembly example is the one that stands out, because it means the generated crate is not tied to a native runtime and a query interface can be compiled for a browser or a wasm target.
PostgreSQL native is about not flattening the database. The project claims full support for custom types, enums and arrays, so a PostgreSQL enum becomes a Rust enum rather than a string, and an array becomes an array rather than a serialised blob. Custom types goes further and lets you map a database type to your own Rust struct, which is the escape hatch when the generated row type is not the shape your domain code wants.
That combination is the real argument for this project over hand writing the queries. The generated code is not a thin wrapper over strings and JSON, it is a typed view of the database, and the deviations from that view are explicit and opt in.
How the approach differs from sqlc, Kanel and jOOQ
The project lists its prior art explicitly, with one line each. sqlc is a Go project that generates type-safe code from SQL. Kanel is a TypeScript project that generates TypeScript types from Postgres. jOOQ is a Java project that generates typesafe SQL from your database schema. Cornucopia is Rust, generates from SQL, and differs most sharply on two axes.
The first axis is the input. The list describes sqlc and Kanel as working from SQL and Postgres, and jOOQ as working from your database schema, whereas Cornucopia's premise is that you write queries and get typed interfaces to exactly those queries. That keeps the generated surface the size of your query set rather than the size of your schema, with no row type for a table you never select from.
The second axis is how the types are established. Cornucopia prepares each query against an actual database and then runs a validation suite on the prepared statements, so the types come from what PostgreSQL returned for that statement, including expression types and inference that a schema based generator has to approximate. The cost of that approach is the one already noted: generation needs a live database with the right schema, so it is not a build step you can run on a machine with no database access.
The third axis is where the generated code lands. Cornucopia emits a separate crate, so the database layer is an explicit dependency in the manifest rather than generated code mixed into your source tree, and the same crate can be shared by several binaries in a workspace.
Version 1.0 absorbed a fork, and the migration is not cosmetic
The most important thing to know before evaluating this project is a piece of project history. A note in the project documentation states that Cornucopia 1.0 merged the Clorinde fork back into the original project, adopting its rewritten code generator, its expanded capabilities and accumulated fixes, with thanks to the fork's author and contributors. If you are upgrading from Cornucopia 0.9.x, the project points to a migration guide.
That note tells you several things at once. It tells you the code generator was rewritten rather than incrementally improved, so the generated output of 1.0 differs from 0.9 in ways that a schema change alone would not explain. It tells you the capabilities grew during the fork period, so the feature set you compare against another tool depends on which line you look at. And it tells you that the project is now a single maintained line again, which is a good thing for anyone starting fresh and a reason to plan for work if you are on 0.9.
The project structure supports the merged state. The repository holds a CHANGELOG.md, a release-plz.toml for release automation, SECURITY.md, CONTRIBUTING.md and a code of conduct, plus a docs/ directory that holds the book, a benches/ directory, a tests/ directory and an examples/ directory where each example is a workspace member.
The versioning is worth noting too. The published versions are cornucopia-v1.0.0 on 2026-05-20 and cornucopia-v1.0.1 on 2026-08-14, and the crate version in the manifest matches 1.0.1. The repository is not archived, and the last push was on 2026-08-25.
Dual licence, a high MSRV, and a parser of its own
Cornucopia is licensed under either the Apache License 2.0 or the MIT licence, at your option, with both licence files in the repository root and the manifest recording the combination as MIT/Apache-2.0. Contributions are dual licensed under the same terms unless stated otherwise, so the licence question is settled for both use and contribution. The practical implication for an organisation is that there is no copyleft obligation and no source disclosure requirement, which matters if the generated crate is going to be part of a commercial product.
The toolchain requirements are stated in the manifest. The edition is 2024, the minimum supported Rust version is 1.88.0, and there is a rust-toolchain.toml and a rustfmt.toml at the repository root, so the toolchain is pinned for contributors and the generated code is formatted consistently.
Two design details in the dependency list are worth a second look. First, the dependency list puts chumsky under a parser heading, so the annotation format is handled by a dedicated parser rather than left to the database, which is what makes the annotation syntax a real, checked format rather than a convention that happens to work. Second, the config handling uses serde, toml and cargo_toml, and the presence of cargo_toml means the generator can read and write the Cargo manifest of the crate it generates, which is how a generated crate ends up as a proper path dependency rather than a loose set of files.
The async story is also visible in the manifest: tokio with the rt-multi-thread feature and the futures crate are direct dependencies, and the async examples are first class members of the workspace rather than an afterthought.
Editorial conclusion
Cornucopia suits a Rust team that already writes plain SQL against PostgreSQL and wants the database to be the source of truth for types, without giving up raw queries for an ORM or a query builder. It is the wrong choice if you cannot give the generator a live database to prepare against, because that step is the core of how it validates queries, and a poor match if you need to change a column type without a schema migration, since the generated crate is derived from the prepared statements. Before adopting, install the generator with cargo install cornucopia, run it against a database that matches production, and read the 1.0 migration guide if you are coming from the 0.9.x line.
Frequently asked questions
How do I install and run Cornucopia?
Install the generator with cargo install cornucopia, write your queries in a SQL file with a --! query name annotation and named parameters, run cornucopia to generate the crate, and add it to your project with a path dependency such as cornucopia = { path = "./cornucopia" }.
Does Cornucopia need a running PostgreSQL database?
Yes. It works by preparing your queries against an actual database and then running a validation suite on them, so generation needs a live database whose schema matches your queries.
What changed between Cornucopia 0.9.x and 1.0?
Version 1.0 merged the Clorinde fork back into the project, adopting its rewritten code generator, expanded capabilities and accumulated fixes, and the project publishes a migration guide for upgrades from the 0.9.x line.
What licence does Cornucopia use?
Cornucopia is licensed under either the Apache License 2.0 or the MIT licence, at your option, and the manifest records the combination as MIT/Apache-2.0. Contributions are dual licensed on the same terms unless stated otherwise.
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/cornucopia-rs-cornucopia)Was this useful?