pg is a free, open source databases project written in Go and released under BSD-2-Clause. It has 5,783 GitHub stars, 415 forks and 124 open issues, and was last pushed 2 months ago. On this registry it ranks #133 of 203 tracked projects in Databases, with 5 head-to-head comparisons available.

What is pg?

go-pg is a PostgreSQL client and ORM for Go that focuses on PostgreSQL-specific features and performance, built for Go developers who want typed models and direct access to types such as hstore, jsonb, and multidimensional arrays.

What it is

go-pg is an ORM and low-level client for PostgreSQL written in Go, distributed as github.com/go-pg/pg/v10 and licensed under BSD-2-Clause. It lives in the Go ecosystem and speaks to PostgreSQL over the standard driver interfaces, while exposing PostgreSQL-only functionality that generic database libraries tend to hide or leave unimplemented. The project is documented at https://pg.uptrace.dev/, with a package reference and runnable examples on pkg.go.dev.

The concrete problem it solves is the boilerplate and impedance mismatch that appear when a Go service talks to PostgreSQL through hand-written SQL and raw database/sql plumbing. go-pg replaces that layer with a DB.Model query API on top of Go structs, and it handles the awkward parts: nullable fields, JSON marshalling, PostgreSQL arrays, hstore columns, composite types, transactions, prepared statements, and connection pooling. Struct fields are nullable by default, and Go zero values such as an empty string, 0, a zero time, an empty map or slice, or a nil pointer are marshalled as SQL NULL unless a tag says otherwise.

Key capabilities

  • Struct tags control nullability and zero-value behaviour: pg:",notnull" adds a SQL NOT NULL constraint, while pg:",use_zero" allows Go zero values through.
  • Native PostgreSQL array support through the array struct tag and the Array wrapper, including multidimensional arrays.
  • hstore columns through the hstore struct tag and the Hstore wrapper; structs, maps, and arrays are marshalled as JSON by default, which covers jsonb columns.
  • Composite PostgreSQL types defined and mapped as Go types.
  • Transactions via DB.Begin, prepared statements via DB.Prepare, and query cancellation and timeouts through context.Context.
  • LISTEN and NOTIFY support through a Listener, and bulk data movement with DB.CopyFrom using COPY FROM and COPY TO.
  • Automatic connection pooling with circuit breaker support, plus query retry on network errors.
  • Go-side type coverage: integers, floats, strings, bool, time.Time, net.IP, net.IPNet, the sql.Null* family, pg.NullTime, and the sql.Scanner and driver.Valuer interfaces.

Who uses it and how

  • Go teams running PostgreSQL-backed services that want models, migrations, and query building in one dependency, using the ORM DB.Model path or dropping to raw SQL where needed.
  • Applications that must read and write PostgreSQL-specific column types such as hstore, jsonb, arrays, and composite types without writing custom scanners.
  • Services that push metrics: go-pg-monitor exposes Prometheus metrics derived from go-pg client statistics.
  • Deployments that outgrow a single database, using go-pg/sharding for sharding.
  • Teams already invested in this API: the README lists example projects including monetr, bunrouter, a gin sample, go-kit, and an aah framework sample, plus tutorials covering GraphQL and a Go, PostgreSQL, and Docker API design walkthrough.

Getting started

Install the current major version with go get github.com/go-pg/pg/v10, then follow the documentation at https://pg.uptrace.dev/ and the package examples on pkg.go.dev. Migrations come from separate projects, go-pg/migrations or robinjoseph08/go-pg-migrations, and model generation is available through the Genna CLI.

How it compares

No list of paid products replaced by this project is provided in the facts. The relevant comparison in the facts is Bun, the successor project by the same maintainer, which offers similar functionality but works with PostgreSQL, MySQL, MariaDB, and SQLite, whereas go-pg targets PostgreSQL only.

When to use it — and when not to

go-pg is in maintenance mode: only critical issues are addressed, and new development happens in Bun. For a new project, Bun is the stated path, and go-pg is best chosen when an existing codebase depends on its API and PostgreSQL-specific behaviour. A self-hoster also carries the usual operational load of running PostgreSQL, and anything requiring MySQL, MariaDB, or SQLite support falls outside this library's scope.

project readme (upstream, from github) — read inline

PostgreSQL client and ORM for Golang

Maintenance mode

go-pg is in a maintenance mode and only critical issues are addressed. New development happens in Bun repo which offers similar functionality but works with PostgreSQL, MySQL, MariaDB, and SQLite.

Golang ORM


Go PkgGoDev Documentation Chat

Tutorials

Ecosystem

Features

Installation

go-pg supports 2 last Go versions and requires a Go version with modules support. So make sure to initialize a Go module:

go mod init github.com/my/repo

And then install go-pg (note v10 in the import; omitting it is a popular mistake):

go get github.com/go-pg/pg/v10

Quickstart

package pg_test

import (
    "fmt"

    "github.com/go-pg/pg/v10"
    "github.com/go-pg/pg/v10/orm"
)

type User struct {
    Id     int64
    Name   string
    Emails []string
}

func (u User) String() string {
    return fmt.Sprintf("User", u.Id, u.Name, u.Emails)
}

type Story struct {
    Id       int64
    Title    string
    AuthorId int64
    Author   *User `pg:"rel:has-one"`
}

func (s Story) String() string {
    return fmt.Sprintf("Story", s.Id, s.Title, s.Author)
}

func ExampleDB_Model() {
    db := pg.Connect(&pg.Options{
        User: "postgres",
    })
    defer db.Close()

    err := createSchema(db)
    if err != nil {
        panic(err)
    }

    user1 := &User{
        Name:   "admin",
        Emails: []string{"admin1@admin", "admin2@admin"},
    }
    _, err = db.Model(user1).Insert()
    if err != nil {
        panic(err)
    }

    _, err = db.Model(&User{
        Name:   "root",
        Emails: []string{"root1@root", "root2@root"},
    }).Insert()
    if err != nil {
        panic(err)
    }

    story1 := &Story{
        Title:    "Cool story",
        AuthorId: user1.Id,
    }
    _, err = db.Model(story1).Insert()
    if err != nil {
        panic(err)
    }

    // Select user by primary key.
    user := &User{Id: user1.Id}
    err = db.Model(user).WherePK().Select()
    if err != nil {
        panic(err)
    }

    // Select all users.
    var users []User
    err = db.Model(&users).Select()
    if err != nil {
        panic(err)
    }

    // Select story and associated author in one query.
    story := new(Story)
    err = db.Model(story).
        Relation("Author").
        Where("story.id = ?", story1.Id).
        Select()
    if err != nil {
        panic(err)
    }

    fmt.Println(user)
    fmt.Println(users)
    fmt.Println(story)
    // Output: User
    // [User User]
    // Story>
}

// createSchema creates database schema for User and Story models.
func createSchema(db *pg.DB) error {
    models := []interface{}{
        (*User)(nil),
        (*Story)(nil),
    }

    for _,

readme truncated — read the full docs on github

Frequently asked questions

Is pg free to use?

pg is open source under the BSD-2-Clause licence. There is no licence fee and no seat count — you can self-host it or, where the project offers one, pay a vendor for a managed version instead.

What does pg do?

Golang ORM with focus on PostgreSQL features and performance

What is pg written in?

pg is primarily written in Go. Its source is publicly available at https://github.com/go-pg/pg, and it has 5,783 GitHub stars.