Skip to content

docs: GORM vs sqlc data-layer decision report#48

Open
AgentWrapper wants to merge 2 commits into
mainfrom
session/ao-5
Open

docs: GORM vs sqlc data-layer decision report#48
AgentWrapper wants to merge 2 commits into
mainfrom
session/ao-5

Conversation

@AgentWrapper
Copy link
Copy Markdown
Contributor

What

Adds docs/orm-decision.md, a decision-grade comparison of GORM vs sqlc for the planned Go + SQLite rewrite of the agent-orchestrator.

Covers all requested dimensions:

  1. Philosophy & approach (runtime ORM vs compile-time codegen)
  2. SQLite-specific support & quirks (drivers, FTS5, JSON1, WAL, concurrency)
  3. Type safety, ergonomics, refactoring
  4. Performance (reflection cost, prepared statements)
  5. Migration tooling & schema evolution
  6. Testing story (in-memory SQLite, mocking generated interfaces, fixtures)
  7. Code generation / build pipeline implications for sqlc
  8. Community health, maintenance, known footguns (N+1, soft-delete, zero-value updates; sqlc dynamic-SQL limits)
  9. Best fit for the agent-orchestrator workload (concurrent sessions, event streams, job queues)
  10. Concrete recommendation + when the other choice wins
  11. Alternatives flagged: sqlx, ent, bun, jet

Recommendation (TL;DR)

Use sqlc as the primary data layer — compile-time-checked, explicit, low-overhead SQL suits a job-queue/event-stream core with a stable schema. Pair with goose/golang-migrate/atlas for migrations (sqlc does none) and a thin sqlx/database/sql escape hatch for dynamic filter queries. Choose GORM only if velocity + pervasive dynamic queries outweigh compile-time safety. Regardless of ORM, the decisive lever is SQLite tuning: WAL + busy_timeout + single writer connection.

How it was produced

Fan-out web research across the comparison dimensions, then an adversarial fact-check pass on the four load-bearing claims (sqlc migrations, GORM footguns, sqlc SQLite/dynamic-SQL limits, SQLite single-writer) — all confirmed — followed by synthesis.

🤖 Generated with Claude Code

Adds a decision-grade comparison of GORM and sqlc for the planned
Go + SQLite rewrite, covering philosophy, SQLite support, type safety,
performance, migrations, testing, codegen pipeline, community health,
workload fit, and alternatives (sqlx/ent/bun/jet).

Recommends sqlc as the primary data layer with an external migration
tool and a hand-written SQL escape hatch for dynamic queries, since
the queue/event-stream core benefits from explicit, compile-time-checked
SQL while SQLite's single-writer model dominates regardless of ORM.

Co-Authored-By: Claude Opus 4.8 (1M context) <noreply@anthropic.com>
@greptile-apps
Copy link
Copy Markdown
Contributor

greptile-apps Bot commented May 31, 2026

Greptile Summary

Adds docs/orm-decision.md, a thorough decision-grade comparison of GORM vs sqlc for the planned Go + SQLite rewrite of the agent-orchestrator, covering eleven dimensions from driver support and WAL concurrency to migration tooling, testing, and build-pipeline implications.

  • The document is technically accurate across all load-bearing claims (sqlc migration design, GORM zero-value/soft-delete footguns, SQLite single-writer constraint, BEGIN IMMEDIATE necessity) and the recommendation for sqlc + golang-migrate/goose + sqlx escape hatch is well-reasoned for a concurrent job-queue/event-stream workload.
  • The ent inline reference correctly uses entgo.io throughout (both inline and in the References section).
  • One minor wording ambiguity exists in the description of the glebarez/sqlite maintenance status (line 53).

Confidence Score: 5/5

Documentation-only addition with no code changes; safe to merge.

This PR adds a single markdown decision document. All load-bearing technical claims in the document were verified as accurate: sqlc's migration-by-design behavior, GORM's zero-value update and soft-delete footguns, SQLite single-writer serialization, and the BEGIN IMMEDIATE / SQLITE_BUSY_SNAPSHOT relationship. No code is modified, so there is no runtime risk.

No files require special attention; the only finding is a minor wording ambiguity in the glebarez/sqlite maintenance status description.

Important Files Changed

Filename Overview
docs/orm-decision.md New decision-grade comparison document for GORM vs sqlc; technically accurate across all major claims with one minor wording ambiguity around the glebarez/sqlite maintenance status.

Flowchart

%%{init: {'theme': 'neutral'}}%%
flowchart TD
    A[Schema Changes / New Query] --> B{Use sqlc?}
    B -- Yes: static hot paths --> C[Write/update query.sql]
    C --> D[sqlc generate]
    D --> E{Parser OK?}
    E -- No: exotic DDL / FTS5 --> F[Keep in migration-only files\nhand-write accessor]
    E -- Yes --> G[Compiler validates\nall call sites]
    G --> H[Run golang-migrate/goose\nat deploy]
    B -- No: dynamic filter query --> I[Write sqlx / raw database/sql\nhand-crafted SQL]
    I --> J[Share single WAL-mode *sql.DB\nSetMaxOpenConns 1 on write pool]
    H --> J
    F --> J
    J --> K{Write transaction?}
    K -- Yes --> L[BEGIN IMMEDIATE\navoids SQLITE_BUSY_SNAPSHOT]
    K -- No --> M[Read pool mode=ro\nmulti-conn OK]
Loading

Reviews (2): Last reviewed commit: "docs: expand ORM report with fact-checke..." | Re-trigger Greptile

Comment thread docs/orm-decision.md Outdated
Replace the report with the deeper, fact-checked version (75 sources,
adversarial verification pass) and correct the inline 'ent.io' domain
to 'entgo.io' per review feedback.

Co-Authored-By: Claude Opus 4.8 (1M context) <noreply@anthropic.com>
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

2 participants