Queryx: An Open-Source Golang ORM with Automatic Schema Management

Github link: GitHub - swiftcarrot/queryx: Schema-first and type-safe ORM for Golang and TypeScript


curl -sf https://raw.githubusercontent.com/swiftcarrot/queryx/main/install.sh  | sh


Queryx uses schema.hcl to describe the database. The following example defines database environments and models:

database "db" {
  adapter = "postgresql"

  config "development" {
    url = "postgres://postgres:postgres@localhost:5432/blog_development?sslmode=disable"

  config "production" {
    url = env("DATABASE_URL")

  generator "client-golang" {}

  model "Post" {
    column "title" {
      type = string
    column "content" {
      type = text

Run the queryx db:create command to create a PostgreSQL database, and then run queryx db:migrate to automatically create the database migration files and database structure. Queryx’s database schema management is built upon Atlas.


Running queryx g generates corresponding ORM code in the db directory. The generated code generates Go types based on the database schema and has no other third-party dependencies except for the lib/pq driver. We hope that the automatically generated code is concise and readable.

Below are some sample code for CRUD operations:

// Create
newPost := c.ChangePost().SetTitle("post title")
post, err := c.QueryPost().Create(newPost)

// Read
post, err := c.QueryPost().Find(1)
posts, err := c.QueryPost().Where(c.PostTitle.EQ("post title")).All()

// Update
updatePost := c.ChangePost().SetTitle("new post title")
err := post.Update(updatePost)
updated, err := c.QueryPost().Where(c.PostTitle.EQ("post title")).UpdateAll(updatePost)

// Delete
err := post.Delete()
deleted, err := c.QueryPost().Where(c.PostTitle.EQ("post title")).DeleteAll()


Relationships between models, including belongs_to, has_one, and has_many, can also be declared in schema.hcl. For example:

model "User" {
  belongs_to "group" {}

  column "name" {
    type = string

model "Group" {
  has_many "users" {}

  column "name" {
    type = string

After declaring the relationship, you can use the generated preload method to avoid n+1 queries. For example:

users, err := c.QueryUser().PreloadGroup().All()
// users[0].Groups

groups, err := c.QueryGroup().PreloadUsers().All()
// groups[0].User

If you are familiar with Rails, you will find that Queryx references many design concepts from ActiveRecord. We hope to replicate the development experience of ActiveRecord. For more queryx usages, please refer to the README documentation, and feel free to discuss in the issue, discussion, and reply. Queryx is currently in beta (v0), and many features are still under development such as MySQL support. We hope to continue to improve the development experience in future versions.

1 Like