ORM Adapters
go-audit ships first-class adapters for the three most popular Go ORMs. Pick the one matching your stack — installation is identical across all three.
Go Audit supports ORMs that expose lifecycle hooks — that's the primary requirement for automatic tracking. Three adapters ship with the project, each in its own sub-module.
Comparison Table
| ORM | Registration | Old-Values Snapshot | Bulk Old-Values |
|---|---|---|---|
| GORM | db.Use(auditgorm.Plugin(auditor)) | Yes (BeforeUpdate) | Yes |
| Bun | auditbun.Register(bunDB, auditor) | Yes (pre-query SELECT) | Yes (base DB only) |
| Ent | client.Use(auditent.Hook(auditor)) | Yes (single-row only) | No (IDs only) |
All three deliver the same stored record shape; the integration plumbing is what differs.
Why No sqlx / pgx / database/sql?
Thin SQL wrappers like sqlx, pgx, and database/sql don't have a
lifecycle model for create/update/delete — they just execute SQL. Go
Audit needs a hook point to capture old values before an update and
compare them after, which these libraries don't provide.
If you need auditing for a raw-SQL code path, use the manual entry point directly:
_ = auditor.RecordDataChange(ctx, audit.DataEntry{
EntityType: "ledger_entries",
EntityID: "le-42",
Action: audit.ActionCreate,
NewValues: map[string]any{"amount": 500},
})See the Data Audit API for the full
DataEntry shape.
Choosing an Adapter
- GORM — most popular, easiest setup, largest plugin ecosystem. Has the most complete snapshot coverage (including soft-delete auto-detection). Default choice for new projects.
- Bun — lightweight, explicit query builder feel. Great for
SQL-ish code with strong typing. Caveat: snapshots run on the base
*bun.DB, not within*bun.Tx, so uncommitted writes in the same transaction aren't visible. - Ent — schema-first code generation with rich graph traversal.
Best if you already build models via
ent codegen. Bulk update/delete operations get one audit row per affected ID, but withoutold_values(ent doesn't expose pre-mutation state for bulk ops).