Skip to main content
Version: 1.1.0

QUARK ORM

Quark is v1.0.0 — the first stable release under SemVer. Phases 0–6 are complete: the core query builder, CRUD, schema-as-code migrations, multi-tenancy, caché, hooks/eventos/audit log, observability, opt-in code generation, read replicas with failover, and pluggable sharding. All six dialects — Oracle included — run on every PR in the integration CI matrix (Oracle boots via docker run rather than testcontainers, whose lifecycle crashed on hosted runners). v1.x keeps API compatibility; breaking changes go to v2.x with a migration path under docs/MIGRATION_vX.Y.Z.md. v1.0 was gated on the qualitative checklist in docs/V1_GATE.md, not a performance target — the ≥3× codegen performance gate was retired (code generation is a type-safety feature, not a speedup). Known limitations consciously deferred to v1.1+ are listed in the v1.0.0 release notes.

QUARK is a modern ORM for Go built around generics, immutable query builders, multi-dialect SQL, and production extension points. It keeps model code close to plain Go structs while still covering migrations, relations, batch operations, transactions, validation, caching, telemetry, and multi-tenancy.

// Query
users, err := quark.For[User](ctx, client).
Where("active", "=", true).
Preload("Posts").
OrderBy("created_at", "DESC").
Limit(20).
List()

// Batch upsert — dialect-specific SQL generated automatically
err = quark.For[Product](ctx, client).UpsertBatch(
feed,
[]string{"sku"},
[]string{"price", "stock"},
)

Why QUARK

CapabilityWhat it gives you
Type-safe APIquark.For[T] returns a *Query[T] — reads map directly back into model structs.
Compile-time column accessorsOpt-in: quark gen emits <Model>Columns so WhereP(UserColumns.Email.Eq(...)) catches column typos and wrong-typed values at build time.
Composable query builderTyped expression AST, subqueries, CTEs, window functions, set operators (UNION/INTERSECT/EXCEPT), pessimistic locking (FOR UPDATE/SKIP LOCKED), optimistic locking (quark:"version").
Immutable buildersQuery methods clone builder state, making shared base queries safe to reuse across goroutines.
SQLGuardIdentifiers, operators, keywords, JSON paths, and JOIN-ON clauses are validated before SQL generation.
Six dialectsPostgreSQL, MySQL, MariaDB, SQLite, MSSQL, and Oracle with dialect-specific DDL, upserts (ON CONFLICT / ON DUPLICATE KEY / MERGE), and pagination.
Full batch suiteCreateBatch, UpsertBatch, UpdateBatch, DeleteBatch — dialect-dispatched and chunked automatically.
Schema-as-code migrationsNeutral introspection, pure-Go Diff, PlanMigration/ApplyPlan round-trip, transactional + resumable execution, distributed migration lock, orchestrated Backfill.
Multi-tenancy (4 strategies)DatabasePerTenant, SchemaPerTenant, RowLevelSecurityClient (WHERE injection, all dialects), and RowLevelSecurityNative (PG-only, engine-enforced via set_config + CREATE POLICY with the quarktenant CLI).
Transactional hooksBefore*/After* (with After* firing post-commit under Client.Tx), BeforeFind/AfterFind, public Tx.OnCommit/Tx.OnRollback + quark.TxFromContext.
Event bus + audit logClient.UseEventBus publishes created/updated/deleted synchronously post-commit (outbound); inbound PostgreSQL LISTEN/NOTIFY via ListenerFactory.CreateListener (dedicated pinned connection, ADR-0019); Client.EnableAuditLog writes quark_audit atomically with the CRUD transaction.
Dirty trackingTracked[T] snapshots at load; Save() emits UPDATE limited to changed fields — closes the "can't set false/0/""" trap.
Production cachéL2 store (memory / Redis) with stampede protection (singleflight + ±jitter + XFetch, ADR-0011; in-process — cross-instance coordination is planned post-v1.0), per-row + table tag invalidation.
ObservabilityOpenTelemetry traces and metrics (counter + duration/rows histograms), WithSpanRedaction (default-on), WithSlowQueryThreshold, WithDeadlockRetry.

Why I built this

After running production services on GORM, three patterns kept causing incidents: every db.Find(&result) forced an interface{} cast the compiler couldn't verify; column names in WHERE clauses were plain strings with no guard against typos or injection in dynamic queries; N+1 queries appeared silently whenever a Preload was forgotten, only surfacing in slow-query logs hours later; and multi-tenant isolation meant copy-pasting WHERE tenant_id = ? everywhere, relying on discipline instead of enforcement. Quark is the ORM I wished existed: generics end the casts, SQLGuard validates every identifier at the API boundary, eager loading is explicit, and multi-tenancy is first-class — not an afterthought.

Documentation map

Guides

SectionContents
InstallationRequirements, drivers, optional packages, env vars
Getting StartedConnect, model, migrate, CRUD
ModelingTags, composite PKs, soft delete, validation, rich types (Nullable/JSON/Array), per-column timezones
Query BuilderFilters, scopes, joins, aggregates, streaming, CTEs, window functions, set operators, locking
Batch OperationsCreateBatch, UpsertBatch, UpdateBatch, DeleteBatch
Relationshas_many, belongs_to, many_to_many, polymorphic
MigrationsMigrate, Sync, schema diff (PlanMigration/ApplyPlan), Backfill, distributed lock
TransactionsCallback, manual, savepoints, isolation levels, WithDeadlockRetry
Lifecycle HooksBefore/After Create/Update/Delete/Find, post-commit semantics, Tx.OnCommit/Tx.OnRollback
Operational Workflowscmd/quark binary, migrations and tenant Go commands
Code GenerationOpt-in quark gen — typed scanners, INSERT binder, compile-time column accessors

Advanced

SectionContents
Multi-TenantDatabasePerTenant, SchemaPerTenant, RowLevelSecurityClient
PostgreSQL Native RLSRowLevelSecurityNative engine-enforced + quarktenant CLI
Event BusClient.UseEventBus, synchronous post-commit, at-least-once
Audit LogClient.EnableAuditLog, atomic with CRUD transaction
Caching & ObservabilityL2 cache, stampede protection, OTel traces + metrics, slow-query log
Read ReplicasWithReplicas read/write split, Sticky(ctx) read-your-writes, automatic failover
ShardingShardRouter, shard-key context routing, HashShardFunc, cross-shard limits

Reference

SectionContents
SQLGuardIdentifier validation, JSON path, JOIN-ON, AllowRawQueries
ComparisonCell-by-cell vs GORM, sqlx, Ent
ConfigurationLimits, WithDialect, WithCacheStore, middleware, observability options
DialectsDialect table, upsert mapping, custom dialects
BenchmarksReproducible database/sql baseline + GORM comparison
ArchitectureRequest lifecycle, SQLGuard, schema evolution
RoadmapImplemented today vs Phase 6 in progress vs long-term
Release NotesPer-version changelog

Install

go get github.com/jcsvwinston/quark
import "github.com/jcsvwinston/quark"

See Installation for driver requirements, optional packages, and test environment variables.