Go Library · PostgreSQL · PGX v5

PostgreSQL ORM,
the Go way

Norm is a production-ready, lightweight ORM and query builder for PostgreSQL on top of PGX v5. Auto-migrations from struct tags, fluent queries, generic repository, soft delete, optimistic locking, transactions, and more.

main.go
package main

import (
    "context"
    "time"

    "github.com/kintsdev/norm"
)

type User struct {
    ID        int64      `db:"id" norm:"primary_key,auto_increment"`
    Email     string     `db:"email" norm:"unique,not_null,index,varchar(255)"`
    Username  string     `db:"username" norm:"unique,not_null,varchar(50)"`
    Password  string     `db:"password" norm:"not_null,varchar(255)"`
    IsActive  bool       `db:"is_active" norm:"default:true"`
    CreatedAt time.Time  `db:"created_at" norm:"not_null,default:now()"`
    DeletedAt *time.Time `db:"deleted_at" norm:"index"`
    Version   int64      `db:"version" norm:"version"`
}

func main() {
    cfg := &norm.Config{Host: "127.0.0.1", Port: 5432, Database: "postgres"}
    kn, _ := norm.New(cfg)
    defer kn.Close()

    // Auto-migrate schema from struct tags
    _ = kn.AutoMigrate(&User{})

    // Generic repository — full CRUD out of the box
    repo := norm.NewRepository[User](kn)
    _ = repo.Create(context.Background(), &User{Email: "[email protected]"})
}
Scroll
Features

Everything you need
for PostgreSQL in Go

From auto-migrations and fluent queries to transactions, read/write splitting, and circuit breakers — all in one lightweight package.

Auto-Migration

Schema migrations from struct tags. Creates tables, columns, indexes, foreign keys, renames, and type changes — all idempotent and transactional.

Fluent Query Builder

Chain Select/Where/Join/OrderBy/Limit, raw SQL, inserts with RETURNING, upserts, and keyset pagination.

Generic Repository

Type-safe CRUD with NewRepository[T]. Bulk create, partial update, scopes, soft delete, and optimistic locking built in.

Soft Delete & Versioning

Soft delete by default with HardDelete() override. Optimistic locking via version tag prevents stale writes.

Transactions

TxManager with transaction-bound QueryBuilder. Automatic commit/rollback with clean Go error handling.

Resilience & Splitting

Read/write splitting with transparent routing, exponential retry/backoff, and circuit breaker with open/half-open/closed states.

Three steps to
production Postgres

01

Define Your Models

Use db and norm struct tags to define columns, indexes, foreign keys, and constraints.

02

Connect & Migrate

Call norm.New(cfg) to connect, then AutoMigrate(&Model{}) to sync your schema.

03

Query & Build

Use the repository for CRUD, or the query builder for complex queries. Transactions, caching, and resilience are built in.

Query Builder

Fluent queries with
type-safe results

Chain methods to build complex queries without writing raw SQL. Supports joins, conditions DSL, keyset pagination, soft delete filtering, and more.

  • Select/Where/Join/OrderBy/Limit/Offset chaining
  • Condition DSL: Eq/Ne/Gt/Lt/In/And/Or
  • INSERT ... RETURNING and ON CONFLICT DO UPDATE
  • Keyset pagination with After/Before cursors
queries.go
// Fluent query builder
var users []User
_ = kn.Query().
    Table("users").
    Where("is_active = ?", true).
    OrderBy("id ASC").
    Limit(10).
    Find(ctx, &users)

// Repository with soft delete
repo := norm.NewRepository[User](kn)
_ = repo.Create(ctx, &user)
_ = repo.Delete(ctx, &user)     // soft delete
_ = repo.HardDelete(ctx, &user) // permanent

// Upsert with ON CONFLICT
_ = kn.Query().
    Table("users").
    OnConflict("email").
    DoUpdate("username", "updated_at").
    Insert(ctx, &user)
models.go
type Post struct {
    ID     int64  `db:"id" norm:"primary_key,auto_increment"`
    Title  string `db:"title" norm:"not_null,varchar(200)"`
    Slug   string `db:"slug" norm:"not_null,unique:tenant_slug"`
    Tenant int64  `db:"tenant_id" norm:"not_null,unique:tenant_slug"`
    UserID int64  `db:"user_id" norm:"not_null,fk:users(id),on_delete:cascade"`
    Amount float64 `db:"amount" norm:"type:decimal(20,8)"`
}

// Supported norm tokens:
// primary_key, auto_increment, unique, unique:group
// index, index:name, using:gin|btree|hash
// fk:table(col), on_delete:cascade|restrict
// not_null, default:expr, version
// type:decimal(20,8), varchar(50), text
// rename:old_column, collate:name
Struct Tags

Schema as code with
powerful struct tags

Define your entire database schema using Go struct tags. Primary keys, composites, indexes, foreign keys with actions, types, defaults, versioning — everything declarative.

  • Composite unique and index groups
  • Foreign keys with cascade/restrict/set null actions
  • Type overrides: decimal(20,8), citext, timestamptz
  • Rename diffs, partial indexes, GIN/btree methods
Performance

Built for
speed at scale

Benchmarked on Apple M3 — go test -bench=. -benchmem. Near-zero allocation in hot paths.

~8ns

StructMapper (cached)

0 alloc · 0 B/op

~127ns

Keyset Pagination

6 allocs · 112 B/op

~229ns

SELECT query build

10 allocs · 368 B/op

~281ns

Placeholder conversion

1 alloc · 144 B/op

Use Cases

PostgreSQL done right
in every Go project

From startup MVPs to regulated financial platforms, Norm gives you the data layer you need without the overhead you don't.

High-Traffic Go APIs

Read/write splitting routes queries to replicas automatically — no manual connection management. PGX v5 means you get the fastest PostgreSQL driver available.

Read/Write Split PGX v5

Multi-Tenant SaaS

Soft delete keeps tenant data recoverable and auditable. Combined with optimistic locking, concurrent updates from multiple tenants stay safe.

Soft Delete Optimistic Lock

Financial & Regulated Backends

Optimistic locking prevents double-spend scenarios. Circuit breaker and retry protect against transient DB failures in production trading systems.

Circuit Breaker Retry

Rapid Prototyping & MVPs

Auto-migrations with full history let you evolve your schema as fast as your product changes — without writing migration files by hand.

Auto-Migrate Schema History

Microservices with Shared Databases

Embed Norm in each service independently. Each service owns its migrations and connection pool — no shared ORM state across services.

Embeddable Isolated

Analytics & Reporting Backends

Fluent query builder generates complex WHERE clauses, JOINs, and aggregations with full type safety — without raw SQL strings scattered across your codebase.

Fluent Builder Type Safe

PGX v5

Native PostgreSQL Driver

Auto

Schema Migrations

R/W

Read/Write Splitting

Ready to simplify
your data layer?

Production-ready PostgreSQL ORM with auto-migrations, fluent queries, generic repository, and enterprise resilience features. Open source, MIT licensed.

Frequently asked questions

What is Norm?

Norm is a production-ready ORM and query builder for PostgreSQL in Go, built on top of PGX v5. It provides auto-migrations, a fluent query builder, generic repository, and enterprise features like soft delete, optimistic locking, and circuit breaker.

How is Norm different from GORM?

Norm is built specifically for PostgreSQL with PGX v5 as the driver — meaning it gets the full benefit of PGX performance without the abstraction overhead of a generic multi-database ORM. Norm also ships with built-in read/write splitting, retry logic, and a circuit breaker.

Does Norm support database migrations?

Yes. Norm includes auto-migration support that detects schema differences and applies changes automatically, while maintaining a full migration history for rollback and auditing.

Can Norm handle high-availability PostgreSQL setups?

Yes. Norm supports read/write splitting — routing read queries to replicas and writes to the primary — along with configurable retry and a circuit breaker for resilience under failure.

Is Norm compatible with PGX v5?

Yes. Norm is built on top of PGX v5, inheriting its high-performance PostgreSQL driver and full support for PostgreSQL-specific data types, arrays, and JSON fields.