ConfigsApr 13, 2026·3 min read

GORM — The Fantastic ORM Library for Go

GORM is the most popular ORM for Go. It provides a developer-friendly API for database operations — auto-migration, associations, hooks, transactions, and query building — with support for PostgreSQL, MySQL, SQLite, and SQL Server.

AI
AI Open Source · Community
Quick Use

Use it first, then decide how deep to go

This block should tell both the user and the agent what to copy, install, and apply first.

package main

import (
    "gorm.io/gorm"
    "gorm.io/driver/sqlite"
)

type User struct {
    gorm.Model
    Name  string
    Email string `gorm:"uniqueIndex"`
    Age   int
}

func main() {
    db, _ := gorm.Open(sqlite.Open("app.db"), &gorm.Config{})
    db.AutoMigrate(&User{})

    // Create
    db.Create(&User{Name: "Alice", Email: "alice@example.com", Age: 30})

    // Read
    var user User
    db.First(&user, "name = ?", "Alice")

    // Update
    db.Model(&user).Update("Age", 31)

    // Delete
    db.Delete(&user)
}

Introduction

GORM is the standard ORM for Go applications. It maps Go structs to database tables and provides a chainable API for CRUD operations, associations, transactions, and migrations. Despite Go's preference for simplicity, GORM fills the gap for developers who want ActiveRecord/Django ORM-style productivity.

With over 40,000 GitHub stars, GORM is used in production by thousands of Go applications. GORM v2 brought significant improvements including a plugin system, better performance, and support for context, batch operations, and prepared statements.

What GORM Does

GORM translates Go struct operations into SQL queries. Define your models as Go structs with tags, and GORM handles table creation (auto-migration), CRUD operations, associations (has-one, has-many, many-to-many), transactions, hooks (callbacks), and raw SQL when needed.

Architecture Overview

[Go Structs (Models)]
type User struct {
    gorm.Model
    Name string
    Posts []Post
}
        |
   [GORM API]
   db.Create(), db.Find(),
   db.Update(), db.Delete()
   Chainable query builder
        |
   [GORM Core]
   SQL generation
   Association handling
   Hook/callback system
   Transaction management
        |
   [Database Drivers]
+-------+-------+-------+
|       |       |       |
[Postgres] [MySQL] [SQLite] [SQL Server]
gorm.io/   gorm.io/ gorm.io/  gorm.io/
driver/    driver/  driver/   driver/
postgres   mysql    sqlite    sqlserver

Self-Hosting & Configuration

import (
    "gorm.io/gorm"
    "gorm.io/driver/postgres"
    "log"
)

// Models with associations
type User struct {
    gorm.Model
    Name    string `gorm:"size:100;not null"`
    Email   string `gorm:"uniqueIndex"`
    Posts   []Post
    Profile Profile
}

type Post struct {
    gorm.Model
    Title  string
    Body   string
    UserID uint
    Tags   []Tag `gorm:"many2many:post_tags;"`
}

type Profile struct {
    gorm.Model
    UserID uint
    Bio    string
}

type Tag struct {
    gorm.Model
    Name string `gorm:"uniqueIndex"`
}

func main() {
    dsn := "host=localhost user=postgres password=secret dbname=myapp port=5432"
    db, err := gorm.Open(postgres.Open(dsn), &gorm.Config{})
    if err != nil {
        log.Fatal(err)
    }

    // Auto-migrate all models
    db.AutoMigrate(&User{}, &Post{}, &Profile{}, &Tag{})

    // Create with associations
    db.Create(&User{
        Name:  "Alice",
        Email: "alice@example.com",
        Posts: []Post{
            {Title: "First Post", Body: "Hello World"},
        },
        Profile: Profile{Bio: "Go developer"},
    })

    // Query with preloading
    var users []User
    db.Preload("Posts").Preload("Profile").Find(&users)

    // Complex query
    var results []User
    db.Where("age > ?", 18).
        Order("created_at desc").
        Limit(10).
        Find(&results)

    // Transaction
    db.Transaction(func(tx *gorm.DB) error {
        if err := tx.Create(&User{Name: "Bob"}).Error; err != nil {
            return err
        }
        return tx.Create(&Post{Title: "New", UserID: 1}).Error
    })
}

Key Features

  • Auto-Migration — create and update tables from Go struct definitions
  • Associations — has-one, has-many, many-to-many, polymorphic
  • Hooks — BeforeCreate, AfterUpdate, BeforeDelete callbacks
  • Transactions — nested transactions with savepoints
  • Preloading — eager loading of associations
  • Batch Operations — batch insert, update, and upsert
  • Raw SQL — execute raw SQL when ORM is not enough
  • Plugin System — extend with custom plugins (soft delete, sharding, etc.)

Comparison with Similar Tools

Feature GORM Ent sqlx sqlc XORM
Type Full ORM Code-gen ORM SQL helper Code-gen SQL Full ORM
Approach Runtime reflection Code generation Raw SQL Raw SQL Runtime reflection
Associations Built-in Built-in Manual Manual Built-in
Migration Auto-migrate Code-gen Manual Manual Auto-sync
Type Safety Moderate Excellent Good Excellent Moderate
Performance Good Very Good Excellent Excellent Good
Learning Curve Low Moderate Low Low Low

FAQ

Q: GORM vs sqlx — which should I use? A: GORM for rapid development with auto-migration, associations, and hooks. sqlx for maximum control, performance, and when you prefer writing SQL directly. Many teams use GORM for CRUD-heavy apps and sqlx for performance-critical queries.

Q: Is GORM performant enough for production? A: Yes. GORM v2 includes prepared statement caching, batch operations, and efficient query building. For hot paths, use raw SQL via db.Raw() or switch to sqlx for specific queries.

Q: How do I handle soft deletes? A: GORM has built-in soft delete via gorm.Model (includes DeletedAt field). Queries automatically filter soft-deleted records. Use db.Unscoped() to include them.

Q: Can I use GORM with multiple databases? A: Yes. Create separate gorm.DB instances for each database. GORM also supports read/write splitting via the DBResolver plugin.

Sources

Discussion

Sign in to join the discussion.
No comments yet. Be the first to share your thoughts.

Related Assets