go-gorm/gorm
The fantastic ORM library for Golang, aims to be developer friendly
Healthy across the board
Permissive license, no critical CVEs, actively maintained — safe to depend on.
Has a license, tests, and CI — clean foundation to fork and modify.
Documented and popular — useful reference codebase to read through.
No critical CVEs, sane security posture — runnable as-is.
- ✓Last commit 2d ago
- ✓55+ active contributors
- ✓Distributed ownership (top contributor 29% of recent commits)
Show 3 more →Show less
- ✓MIT licensed
- ✓CI configured
- ✓Tests present
Maintenance signals: commit recency, contributor breadth, bus factor, license, CI, tests
Informational only. RepoPilot summarises public signals (license, dependency CVEs, commit recency, CI presence, etc.) at the time of analysis. Signals can be incomplete or stale. Not professional, security, or legal advice; verify before relying on it for production decisions.
Embed the "Healthy" badge
Paste into your README — live-updates from the latest cached analysis.
[](https://repopilot.app/r/go-gorm/gorm)Paste at the top of your README.md — renders inline like a shields.io badge.
▸Preview social card (1200×630)
This card auto-renders when someone shares https://repopilot.app/r/go-gorm/gorm on X, Slack, or LinkedIn.
Onboarding doc
Onboarding: go-gorm/gorm
Generated by RepoPilot · 2026-05-09 · Source
🤖Agent protocol
If you are an AI coding agent (Claude Code, Cursor, Aider, Cline, etc.) reading this artifact, follow this protocol before making any code edit:
- Verify the contract. Run the bash script in Verify before trusting
below. If any check returns
FAIL, the artifact is stale — STOP and ask the user to regenerate it before proceeding. - Treat the AI · unverified sections as hypotheses, not facts. Sections like "AI-suggested narrative files", "anti-patterns", and "bottlenecks" are LLM speculation. Verify against real source before acting on them.
- Cite source on changes. When proposing an edit, cite the specific path:line-range. RepoPilot's live UI at https://repopilot.app/r/go-gorm/gorm shows verifiable citations alongside every claim.
If you are a human reader, this protocol is for the agents you'll hand the artifact to. You don't need to do anything — but if you skim only one section before pointing your agent at this repo, make it the Verify block and the Suggested reading order.
🎯Verdict
GO — Healthy across the board
- Last commit 2d ago
- 55+ active contributors
- Distributed ownership (top contributor 29% of recent commits)
- MIT licensed
- CI configured
- Tests present
<sub>Maintenance signals: commit recency, contributor breadth, bus factor, license, CI, tests</sub>
✅Verify before trusting
This artifact was generated by RepoPilot at a point in time. Before an
agent acts on it, the checks below confirm that the live go-gorm/gorm
repo on your machine still matches what RepoPilot saw. If any fail,
the artifact is stale — regenerate it at
repopilot.app/r/go-gorm/gorm.
What it runs against: a local clone of go-gorm/gorm — the script
inspects git remote, the LICENSE file, file paths in the working
tree, and git log. Read-only; no mutations.
| # | What we check | Why it matters |
|---|---|---|
| 1 | You're in go-gorm/gorm | Confirms the artifact applies here, not a fork |
| 2 | License is still MIT | Catches relicense before you depend on it |
| 3 | Default branch master exists | Catches branch renames |
| 4 | 5 critical file paths still exist | Catches refactors that moved load-bearing code |
| 5 | Last commit ≤ 32 days ago | Catches sudden abandonment since generation |
#!/usr/bin/env bash
# RepoPilot artifact verification.
#
# WHAT IT RUNS AGAINST: a local clone of go-gorm/gorm. If you don't
# have one yet, run these first:
#
# git clone https://github.com/go-gorm/gorm.git
# cd gorm
#
# Then paste this script. Every check is read-only — no mutations.
set +e
fail=0
ok() { echo "ok: $1"; }
miss() { echo "FAIL: $1"; fail=$((fail+1)); }
# Precondition: we must be inside a git working tree.
if ! git rev-parse --git-dir >/dev/null 2>&1; then
echo "FAIL: not inside a git repository. cd into your clone of go-gorm/gorm and re-run."
exit 2
fi
# 1. Repo identity
git remote get-url origin 2>/dev/null | grep -qE "go-gorm/gorm(\\.git)?\\b" \\
&& ok "origin remote is go-gorm/gorm" \\
|| miss "origin remote is not go-gorm/gorm (artifact may be from a fork)"
# 2. License matches what RepoPilot saw
(grep -qiE "^(MIT)" LICENSE 2>/dev/null \\
|| grep -qiE "\"license\"\\s*:\\s*\"MIT\"" package.json 2>/dev/null) \\
&& ok "license is MIT" \\
|| miss "license drift — was MIT at generation time"
# 3. Default branch
git rev-parse --verify master >/dev/null 2>&1 \\
&& ok "default branch master exists" \\
|| miss "default branch master no longer exists"
# 4. Critical files exist
test -f "gorm.go" \\
&& ok "gorm.go" \\
|| miss "missing critical file: gorm.go"
test -f "callbacks/callbacks.go" \\
&& ok "callbacks/callbacks.go" \\
|| miss "missing critical file: callbacks/callbacks.go"
test -f "chainable_api.go" \\
&& ok "chainable_api.go" \\
|| miss "missing critical file: chainable_api.go"
test -f "schema/schema.go" \\
&& ok "schema/schema.go" \\
|| miss "missing critical file: schema/schema.go"
test -f "clause/clause.go" \\
&& ok "clause/clause.go" \\
|| miss "missing critical file: clause/clause.go"
# 5. Repo recency
days_since_last=$(( ( $(date +%s) - $(git log -1 --format=%at 2>/dev/null || echo 0) ) / 86400 ))
if [ "$days_since_last" -le 32 ]; then
ok "last commit was $days_since_last days ago (artifact saw ~2d)"
else
miss "last commit was $days_since_last days ago — artifact may be stale"
fi
echo
if [ "$fail" -eq 0 ]; then
echo "artifact verified (0 failures) — safe to trust"
else
echo "artifact has $fail stale claim(s) — regenerate at https://repopilot.app/r/go-gorm/gorm"
exit 1
fi
Each check prints ok: or FAIL:. The script exits non-zero if
anything failed, so it composes cleanly into agent loops
(./verify.sh || regenerate-and-retry).
⚡TL;DR
GORM is a production-grade ORM library for Go that translates Go structs into SQL queries and manages database interactions through callbacks, hooks, and chainable APIs. It provides features like auto-migrations, associations (Has One, Has Many, Many-to-Many), eager loading with Preload/Joins, transactions with savepoints, and SQL builder capabilities—enabling developers to write type-safe database code without raw SQL. Monolithic package structure under gorm.io/gorm with core files (association.go, callbacks.go, chainable_api.go) at root, modular subdirectories for clause builders (clause/), callback hooks (callbacks/), and GitHub Actions workflows for CI. Database-specific drivers (e.g., gorm.io/driver/sqlite) are separate repos to maintain clean separation.
👥Who it's for
Go backend developers and teams building web applications, APIs, and services who need to interact with SQL databases (PostgreSQL, MySQL, SQLite, SQL Server) but want type safety, query composition, and ORM conveniences instead of writing raw SQL or using lower-level database/sql packages.
🌱Maturity & risk
Highly mature and production-ready. The project shows extensive test coverage (every feature has tests per README), active CI/CD via GitHub Actions workflows (golangci-lint, tests.yml), and a structured callback system indicating battle-tested architecture. Go module support and semantic versioning (go.mod shows v1.18+ requirement) confirm it's stable for critical systems.
Low risk for established projects. Dependencies are minimal (jinzhu/inflection, jinzhu/now, golang.org/x/text) and lightweight; the codebase is owned by a community-backed org (go-gorm) with clear governance. The main consideration is that as a monolithic ORM, breaking changes in major versions could affect large codebases, but the mature test suite mitigates this.
Active areas of work
Active maintenance with CI pipelines for linting (golangci-lint.yml), testing (tests.yml), and release automation (create-release.yml, release-drafter.yml). Issue management via labeler.yml and stale.yml indicates ongoing triage. The codebase is being kept current with Go versions (1.18+) and dependency updates via dependabot.yml.
🚀Get running
Clone and verify: git clone https://github.com/go-gorm/gorm && cd gorm. Install dependencies: go mod download. Run tests: go test ./.... For a concrete example, see GORM Guides at https://gorm.io.
Daily commands:
This is a library, not a runnable application. Use it as a dependency in another Go project via go get gorm.io/gorm. For development within GORM itself, run go test ./... to execute the test suite, or golangci-lint run to lint per .golangci.yml config.
🗺️Map of the codebase
gorm.go— Core GORM instance struct and initialization—entry point for all ORM operations and database connectionscallbacks/callbacks.go— Callback registry and execution engine that powers all hooks (Before/After Create/Update/Delete/Find)—essential for understanding GORM's lifecyclechainable_api.go— Chainable query builder interface (Where, Select, Joins, Preload, etc.)—defines the public fluent API that developers interact withschema/schema.go— Schema reflection and model introspection for field relationships and constraints—critical for auto-migrations and association handlingclause/clause.go— SQL clause abstraction layer (WHERE, JOIN, INSERT, UPDATE, DELETE)—bridges Go query builders to database-agnostic SQL generationfinisher_api.go— Terminal query operations (Find, Create, Update, Delete, Scan)—where chainable methods resolve into actual database callsassociation.go— Association loading and management (HasOne, HasMany, BelongsTo, ManyToMany)—handles relationship queries and preloading
🛠️How to make changes
Add a custom callback hook (e.g., logging plugin)
- Create a callback function matching
func(db *gorm.DB)signature (callbacks/callbacks.go) - Register it in your initialization code using
db.Callback().Create().Register(callbackName, callbackFunc)for your desired operation (Create/Update/Delete/Query) (callbacks/callbacks.go) - Access the prepared statement and execution flow via
db.Statementto inspect/modify queries and results (gorm.go)
Add support for a custom data type
- Implement the
Valuerinterface (database/sql/driver) on your type to convert Go→SQL (interfaces.go) - Implement the
Scannerinterface (database/sql) on your type to convert SQL→Go (interfaces.go) - Tag your struct field with
gorm:"type:your_sql_type"and GORM will use your Valuer/Scanner in queries and migrations (schema/field.go)
Extend GORM with a custom clause (e.g., hints, locking)
- Create a struct implementing
clause.Expression(withBuild(builder clause.Builder)method) (clause/expression.go) - Add a chainable method on
DB(in your code or by usingDB.Session()pattern) that appends your clause todb.Statement.Clauses(chainable_api.go) - Your Build() method will be called during statement rendering to inject SQL; see
clause/locking.goorclause/on_conflict.gofor examples (clause/clause.go)
Add a custom migrator for a new database dialect
- Implement the
migrator.Migratorinterface methods (CreateTable, DropTable, AddColumn, etc.) (migrator/migrator.go) - Map SQL data types to your dialect's column type names in the ColumnTypes() method (
migrator/column_type.go) - Set your migrator on the DB instance with
db.Migrator = yourMigratorbefore calling AutoMigrate (gorm.go)
🔧Why these technologies
- Go interfaces (Valuer, Scanner, Clauser, Migrator) — Enables database-agnostic abstractions and third-party dialect plugins (sqlite, postgres, mysql, sqlserver drivers are separate repos)
- Callback/Hook system (before/after operations) — Allows user-defined extensions and business logic injection without modifying core; powers soft deletes, validation, audit logging
- Prepared statement pooling with LRU cache — Reduces query parsing overhead and improves concurrency on high-throughput applications
- Reflection-based schema introspection (struct tags, field types) — Eliminates boilerplate schema definitions; enables auto-migration and relationship discovery from Go structs
- Clause composition pattern (WHERE, JOIN, SELECT as composable objects) — Provides flexibility to build complex SQL without string concatenation; database-agnostic SQL generation
⚖️Trade-offs already made
-
Heavy reliance on Go reflection for schema parsing
- Why: Simplifies user API (just struct tags) and enables runtime flexibility
- Consequence: Minor startup cost for model introspection; requires careful struct tag parsing; harder to statically optimize
-
Separate prepared statement cache per DB instance (not global)
- Why: Avoids cache contention and allows per-connection tuning; simpler memory isolation
- Consequence: Slight duplication across multiple DB instances; developers must share DB instances for optimal cache re
🪤Traps & gotchas
GORM uses reflection heavily for struct field scanning and relationship inference—this can have subtle performance implications in tight loops. The callback system relies on struct tags for metadata (gorm tag), and incorrect tags silently fail rather than error. Hook ordering (Before/After Create vs Save) can be counterintuitive (Save wraps Create). Database driver compatibility varies (SQLite is bundled but PostgreSQL/MySQL require separate driver imports). Finally, auto-migration uses reflection to infer schemas, so non-standard Go types may need explicit migration definitions.
🏗️Architecture
💡Concepts to learn
- Callback Hooks System — GORM's entire operation model revolves around registering and executing hooks at fixed lifecycle points—understanding callbacks/callbacks.go is essential to extending GORM or debugging unexpected behavior
- Clause Composition Pattern — GORM generates SQL by composing individual clause objects (WHERE, JOIN, GROUP BY, etc.) rather than string concatenation—understanding clause/ shows how SQL builders prevent injection and compose complex queries
- Reflection-Based Field Scanning — GORM uses Go reflection to inspect struct fields, infer column names, and map query results—critical for understanding performance implications and why struct tags matter
- Chainable/Fluent API — GORM's query builder uses method chaining (db.Where().Preload().Limit()) to compose queries—exemplifies the builder pattern and why chainable_api.go returns *DB for continuity
- Lazy vs Eager Association Loading — GORM distinguishes between implicit lazy loading (N+1 problem) and explicit eager loading (Preload/Joins)—fundamental to writing performant queries and understanding callbacks/preload.go
- Polymorphic Associations — GORM supports single-table inheritance and polymorphic relationships (one model associating to many types)—advanced relational pattern visible in association.go requiring careful schema design
- Context Propagation & Prepared Statements — GORM integrates Go contexts for cancellation and prepared statement caching for performance—essential for building production services with timeout handling and query reuse
🔗Related repos
go-gorm/datatypes— Provides extended data types (JSONQuery, Date, Time, etc.) that integrate directly with GORM structs for richer type supportgo-gorm/gen— Official code generation tool that generates type-safe query builders from GORM models, eliminating string-based query buildinggo-gorm/hints— Optimizer/index hint integration library used alongside GORM for database-specific performance tuning (mentioned in README)ent/ent— Alternative Go ORM with code-gen-first design; compare for different approach to type safety and schema managementupper/db— Another Go ORM offering simpler API surface; useful comparison for minimalist vs feature-rich philosophy
🪄PR ideas
To work on one of these in Claude Code or Cursor, paste:
Implement the "<title>" PR idea from CLAUDE.md, working through the checklist as the task list.
Add comprehensive test coverage for clause/expression.go and clause/with.go
The clause package has extensive test files for most components (clause_test.go, where_test.go, joins_test.go, etc.), but expression.go and with.go lack corresponding test files. These are critical SQL-building components that need unit tests to ensure SQL expression building and CTE (Common Table Expressions) functionality work correctly across databases. This is a high-impact contribution that improves test coverage for core query building logic.
- [ ] Create clause/expression_test.go with tests for expression parsing, binary operations, and nested expressions
- [ ] Create clause/with_test.go with tests for WITH clause construction, nested CTEs, and recursive queries
- [ ] Add edge cases for special characters, subqueries, and parameter binding in both test files
- [ ] Run existing tests to ensure no regressions: go test ./clause/...
Add GitHub Actions workflow for database driver compatibility testing
The repo has tests.yml workflow but only mentions sqlite3 driver. GORM supports multiple database drivers (MySQL, PostgreSQL, SQLServer, etc.) via separate driver repos. Adding a workflow that tests against common databases would catch driver-specific issues early. The workflow should use Docker services to spin up test databases and validate core GORM functionality works across drivers.
- [ ] Create .github/workflows/db-driver-tests.yml with matrix strategy for MySQL, PostgreSQL, SQLite
- [ ] Use docker-compose services in the workflow to start database containers (postgres:latest, mysql:latest)
- [ ] Run go test with different driver imports/configurations for each database type
- [ ] Document in README which drivers are officially tested in CI
Add integration tests for nested transaction savepoints in callbacks/transaction.go
The README advertises 'Nested Transactions, Save Point, RollbackTo to Saved Point' as a key feature, but callbacks/transaction.go and callbacks/transaction_test.go lack comprehensive integration tests for complex nested transaction scenarios. Contributions should add tests for savepoint rollback edge cases, nested rollbacks with mixed commits/rollbacks, and error handling in transaction chains.
- [ ] Review callbacks/transaction.go to understand savepoint implementation
- [ ] Add tests in callbacks/transaction_test.go for: basic nested transactions, multiple savepoints, partial rollbacks, and error propagation
- [ ] Add tests for SavePoint/RollbackTo API with real database operations (not mocked)
- [ ] Test edge cases: rolling back to non-existent savepoints, rolling back after transaction commit, concurrent nested transactions
🌿Good first issues
- Add missing unit test coverage for clause/expression.go similar to existing benchmarks in clause/benchmarks_test.go—improve test surface for expression building
- Document the callback execution order in callbacks/interfaces.go with concrete examples (e.g., clarify that BeforeSave runs before BeforeCreate)—improves hook usability for newcomers
- Implement missing error wrapping in helper.go callback helpers to surface clearer error messages when associations fail to load—increases debuggability
⭐Top contributors
Click to expand
Top contributors
- @jinzhu — 29 commits
- @1911860538 — 4 commits
- @smf-h — 3 commits
- @miladev95 — 3 commits
- @liov — 3 commits
📝Recent commits
Click to expand
Recent commits
3322929— fix(migrator): add nil guards to ColumnType methods to prevent panic (#7767) (lihan3238)40cd2af— ci: switch tests Go matrix to stable/oldstable and update setup-go (#7726) (smf-h)ba38501— chore(ci): bump actions/stale to v9 (#7696) (Olexandr88)c1f742d— fix: don't override alterColumn when defaults match (#7728) (qqxhb)c14d3ac— update github ci golang version (jinzhu)47f5424— Add package comments to fix ST1000 warnings (#7708) (twocs)09530b8— generics: populate WithResult error (#7723) (qqxhb)61520d7— fix(utils): restore FileWithLineNum caller depth and add regression test (#7717) (smf-h)01916e7— tests: skip customized foreign key many2many on MySQL 8.4+ (#7727) (smf-h)8d8af3f— Fix tiny cut-and-paste typo in error message (#7738) (snelg)
🔒Security observations
The GORM codebase demonstrates reasonable security practices as a core ORM library with no hardcoded secrets or obvious critical vulnerabilities. However, there are medium-priority concerns around SQL injection prevention enforcement, dependency management, and callback safety. The library relies heavily on developer responsibility for secure implementation. Dependencies are relatively minimal and well-maintained. The project would benefit from enhanced documentation on secure usage patterns and explicit validation guidelines for user-supplied data in queries and associations. Overall security posture is acceptable for a well-established ORM, but applications using it must implement additional security layers at the web framework level.
- High · Potential SQL Injection via Raw Query Methods —
callbacks/raw.go, clause/where.go, finisher_api.go. The codebase contains raw SQL query capabilities (indicated by callbacks/raw.go and raw query patterns in clause building). Without explicit evidence of parameterized query enforcement throughout, raw SQL methods could be vulnerable to SQL injection if user input is directly concatenated into queries. Fix: Ensure all SQL query methods enforce parameterized queries and prepared statements. Implement input validation and sanitization for any dynamic query construction. Provide clear documentation warning against string concatenation in SQL queries. - Medium · Dependency: golang.org/x/text v0.20.0 - Verify Currency Code Handling —
go.mod - golang.org/x/text v0.20.0. The golang.org/x/text v0.20.0 dependency should be verified for known vulnerabilities in Unicode and text handling, particularly in contexts where user-supplied data is processed. Fix: Rungo list -u -m allto check for available updates. Consider upgrading to the latest patch version. Monitor security advisories for this dependency. - Medium · Indirect Dependency: mattn/go-sqlite3 v1.14.22 —
go.mod - github.com/mattn/go-sqlite3 v1.14.22 (indirect). The sqlite3 driver is included as an indirect dependency. Ensure this version has no known CVEs. SQLite driver vulnerabilities could impact applications using SQLite backend. Fix: Verify the version against known CVE databases. Consider updating to the latest version. Assess if SQLite is necessary for production use cases. - Medium · Insecure Deserialization Risk in Hooks/Callbacks —
callbacks/callbacks.go, callbacks/interfaces.go, association.go. The hooks system (Before/After Create/Save/Update/Delete/Find) and callbacks pattern could potentially allow unsafe deserialization or code execution if user-provided data is processed without proper validation in hook handlers. Fix: Document secure practices for hook implementation. Validate and sanitize all data processed in hook functions. Avoid deserializing untrusted data in hooks. - Low · Missing Input Validation in Association Handling —
association.go, callbacks/associations.go, clause/association.go. Association operations (Has One, Has Many, Belongs To, Many To Many) may require robust input validation to prevent unintended data access or manipulation through malformed association queries. Fix: Implement comprehensive validation for association keys and identifiers. Add tests for malformed association queries. Document association security best practices. - Low · No Evidence of CSRF Protection in ORM Layer —
Project scope - architectural. As an ORM library, GORM itself doesn't handle CSRF, but applications built with it must implement their own CSRF protection at the web framework level. Fix: Document security considerations for applications using GORM. Recommend using CSRF protection middleware in the web framework (e.g., gorilla/csrf). This is expected application-level responsibility, not ORM responsibility. - Low · Missing Security Headers in Generated Code/Documentation —
README.md, Documentation. No visible security configuration or security headers documentation for applications built with GORM. Fix: Add a security best practices section to README. Include guidance on preventing common vulnerabilities (SQLi, data exposure, etc.) when using GORM.
LLM-derived; treat as a starting point, not a security audit.
👉Where to read next
- Open issues — current backlog
- Recent PRs — what's actively shipping
- Source on GitHub
Generated by RepoPilot. Verdict based on maintenance signals — see the live page for receipts. Re-run on a new commit to refresh.