CLI tool
zenstackhq/zenstack avatar
zenstackhq/zenstack

zenstack: version 3 threw out the engine, and the default branch is dev

Modern data layer for TypeScript apps - type-safe ORM, built-in access control, automatic query services

2,947 stars157 forksTypeScriptMIT

At a glance

What is it?
ZenStack is a schema-first data layer for TypeScript that rebuilt its query engine in version 3, kept the query API of the tool it is replacing, and is now selling the absence of a compiled binary as the headline benefit. The repository also shows its own machinery in the open: a development branch, a version bump that runs as a workflow, three publishing channels and one of them on a private registry.
Who is it for?
Adopt ZenStack if the reason you are leaving a schema-first ORM is that you do not want a compiled engine in your dependency tree, because that is precisely what version 3 changes and precisely what the page argues. Read the breaking-changes document in the root before trusting the word compatible, since compatibility is claimed for the schema and the query API rather than for the engine.
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 received new commits within the last day.
What is it written in?
Mainly TypeScript, according to GitHub's language statistics.

Answers come from the project's GitHub data, last synced on October 5, 2026, and from our analysis. They are not legal advice.

Editorial analysis

Version 3 replaced the engine and kept the query API

The what is new section is the most important paragraph on the page, and it is a rewrite rather than a feature. Version 3 replaced the ORM it previously built on with its own engine, built on top of a query builder, while keeping a query API compatible with the one it replaced. The page calls that a bold decision and links a blog post explaining why. Then it makes the pitch that matters, framed as benefits you get even without touching the advanced features. First, a pure TypeScript implementation with no compiled components in other languages, which is the real point: a JavaScript runtime does not have to download and instantiate a binary to run your queries. Second, more inference from the type system and less generated code. Third, a fully typed query-builder API as an escape hatch, which the page frames as better than the raw query or typed SQL paths offered by the tool it is replacing. So the migration argument is about what leaves your dependency tree, not about what you can write afterwards.

Compatibility is claimed for the schema and the API, not for the engine

Read the feature list closely and the shape of the compatibility claim becomes clear. The ORM is described as schema-first and compatible with another tool's schema and its API. Nothing in the list claims the engine underneath is the same, because it is not. The versatile-API bullet pairs high-level ORM queries with a low-level query builder in the same product, which is how the two audiences are meant to coexist: write against the high level until you cannot, then drop to the builder. Around that sit access control and data validation, modelling patterns such as polymorphism, automatic CRUD web APIs with adapters for popular frameworks, automatic frontend hooks for one particular query library, and schema generation for a validation library. The repository root carries a document devoted to breaking changes, which is where you would look before taking the word compatible literally. The sample set is split the same way: a bare ORM sample next to full framework samples for four frameworks and a shared library.

The default branch is dev, and four scripts move the code

The repository's default branch is not main, it is dev, and the manifest encodes the whole release path in four scripts. One opens a pull request with the first commit's message filled in, targeting dev, which is what a contributor's branch should aim at. One opens a pull request with a title saying it merges dev into main and an empty body, which is the release pull request and nothing more clever than that. Two more trigger a version-bump workflow on dev, one for a patch and one for a minor, passing the kind of bump as an input. So the version is not edited by hand and the release is not cut from dev directly; a workflow decides the number and a pull request moves the branch. The consequence for an outside contributor is simple and worth internalising: a pull request against main is aimed at the wrong place, and the recent tag history shows the consequence of that in reverse, with three patch releases in eight days.

Three install routes, and the manual one ends with a custom file extension

Installation is offered three ways and the third is the one to read carefully. The first scaffolds a new project with the create command, and the page is specific that what you get is a simple TypeScript command line application with the data layer already configured, which is a narrower starting point than most tooling that claims to scaffold anything. The second initializes an existing project with the CLI's init command. The third is manual, and it is three commands:

bash
npm install -D @zenstackhq/cli
npm install @zenstackhq/schema @zenstackhq/orm

followed by one instruction that carries the real information: create a folder named for the toolkit and put a schema file with a custom extension inside it. So the schema language is not TypeScript, even though everything else is, and both the folder name and the file extension are fixed. There is also a browser-based quick start linked from the page that opens a sample project with the schema file already open in an editor, which is the fastest way to see what the schema looks like without installing anything.

Prereleases go to the project's own registry host

There are four publishing scripts in the manifest and they form a small release system. One publishes every workspace package to the public registry. One publishes a canary tag while explicitly skipping the git checks that would otherwise stop a dirty tree from publishing, which is what makes it usable from a feature branch. One force-publishes to a completely different registry host, a preview subdomain of the project's own domain, and the fourth unpublishes from that host. So the project runs a private registry for prerelease builds, which is how you would consume a version that has not been released publicly. It is a genuinely useful arrangement and it has one requirement nobody can guess: your package manager configuration has to be pointed at that host. The three script variants also tell you the release cadence, since patch, minor and preview are all one command away, and the public one publishes every package in the workspace rather than one, so a release is all-or-nothing.

One test script, three database engines, and a separate coverage path

Testing is arranged so that the same suite runs three times. The plain test script delegates to the task runner across the workspace, and then three provider-specific scripts exist that set an environment variable to one database engine and run the same thing, for SQLite, for PostgreSQL and for MySQL. A fourth script runs all three in sequence, which is what a full check costs in wall-clock time. There is also a coverage command that invokes the test runner directly with coverage rather than going through the task runner, so the coverage report and the pass or fail signal come from two different execution paths. For a project whose pitch is that its engine works across databases rather than only one, that is the right shape of test matrix, and it is also the reason a pull request from a contributor takes a while to go green. The manifest pins one package manager version, and the build, watch, lint and test scripts all delegate to the task runner with per-package tasks behind them.

A to-do file, a development container, and a review bot that also sponsors it

The repository root is where this project's automation shows itself. There is a document listing breaking changes, which for a project whose current major version is itself the rewrite is the migration manual in one file. There is a to-do document, which is rarer and tells you the maintainers work in the open rather than in issues. There is a development container definition so a contributor's editor and runtime versions match without a wiki page. There are git hooks, a formatting configuration with its own ignore list, an agent instruction file, and a patches directory, which is how this package manager applies modifications to dependencies that do not carry them upstream. And there is a configuration file for an automated review service, which is listed among the current sponsors. That last overlap is a small governance fact worth noting rather than a complaint: the tool that reads every pull request is also a party to the project's funding, which is disclosed in the open on the page. Documentation lives in a separate repository with its own contributors list.

Editorial conclusion

Adopt ZenStack if the reason you are leaving a schema-first ORM is that you do not want a compiled engine in your dependency tree, because that is precisely what version 3 changes and precisely what the page argues. Read the breaking-changes document in the root before trusting the word compatible, since compatibility is claimed for the schema and the query API rather than for the engine. Two operational facts to plan around. Development happens on a branch called dev, with versions bumped by a workflow and a pull request opening the move to main, so a contribution targets dev and not the branch you would guess. And prereleases are published to the project's own registry host, which is the mechanism to use if you want to test an upcoming version rather than the stable one. Note also that the full test run executes the suite three times, once per database engine. The default branch was last pushed on 2026-10-02 and the newest release is v3.9.7 from 2026-09-30.

Frequently asked questions

Is ZenStack a drop-in replacement for Prisma?

The page claims compatibility with Prisma's schema and its API, and lists three benefits of version 3 as a drop-in replacement even without using advanced features: a pure TypeScript implementation with no Rust or WebAssembly components, more type inference with less code generation, and a fully typed query-builder escape hatch. It also notes that version 3 replaced the Prisma ORM with its own engine built on a query builder, and the repository root carries a breaking-changes document.

What is a good alternative to Prisma?

This repository cannot answer that as an independent comparison, and it does not try: the page makes no list of alternatives. What it does is describe itself as schema-first and compatible with Prisma's schema and API, and it argues that the reason to move is to drop a compiled engine from a JavaScript runtime, offering a fully typed query builder as the escape hatch instead of raw queries or typed SQL.

Which databases does ZenStack test against?

Three, according to the manifest. There are separate test scripts that set a provider environment variable for SQLite, for PostgreSQL and for MySQL, and a fourth that runs all three in sequence. A coverage command exists as well, and it runs the test runner directly rather than through the task runner, so coverage and the pass or fail result come from different execution paths.

what is zenstack private limited

Nothing in this repository relates to that name. This is the ZenStack TypeScript database toolkit, published by a team with a contact address on the project's own domain, MIT licensed with the licence file at the root of the repository, and released under version tags like v3.9.7.

is zenstack legit

The page makes no trust claims, and there is nothing on it that would answer the question either way. What you can check is concrete: an MIT licence file in the root, named current and previous sponsors, a chat server, a separate public documentation repository with its own contributors list, three patch releases in eight days, a development branch as the default, and a breaking-changes document committed beside the readme.

Official sources

  1. License: MIT
  2. Project website
  3. README
  4. Releases
  5. zenstackhq/zenstack on GitHub
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.

Add this badge to your README

markdown
[![Hysen Labs](https://hysenlabs.com/badge/zenstackhq-zenstack.svg)](https://hysenlabs.com/projects/zenstackhq-zenstack)