Sqlc: Compile SQL to type-safe code

Sqlc approach and perceived benefits

  • Generates type-safe code from plain SQL, avoiding ORM/query-builder DSLs.
  • Users like keeping SQL in .sql files and getting checked, compiled interfaces in Go and other languages.
  • Appreciated for small and medium projects where developers are comfortable writing SQL directly.
  • Some teams report successful migrations from ORMs (e.g., GORM) and prefer sqlc’s simpler, explicit abstractions.

Limitations and pain points

  • A recurring complaint is lack of first-class support for dynamic queries; workarounds (e.g., CASE-based conditions) are seen as clumsy.
  • Some say sqlc is “great until it breaks,” citing loss of context in joins and allowing invalid columns.
  • One commenter argues it works only for “basic stuff,” failing on more complex use cases; others dispute this, saying complex queries are fine if not overused.

Dynamic queries vs static SQL

  • Sqlc’s design principle is static queries in application code so it’s always clear what hits the database.
  • Critics counter that composition of query fragments is a major reason to use builders, and that if queries must be static, stored procedures might be simpler.

Comparisons with other libraries and ecosystems

  • Go: go-jet, sqlboiler, XO, GORM mentioned. Jet is praised as a jOOQ-like builder with good type safety and debugging, but lacks some DB features and reverse-SQL translation.
  • Rust: SQLx and Cornucopia compared; some feel sqlc adds little beyond SQLx-style macros.
  • JVM: jOOQ repeatedly cited as a gold standard for type-safe SQL.
  • Kotlin/Android: SQLDelight seen as a close analogue.
  • TypeScript/JS: Kysely, Slonik, and Prisma’s TypedSQL highlighted for type-safe SQL without heavy codegen.

Schema evolution, migrations, and rollbacks

  • Discussion on how codegen interacts with schema changes: some avoid destructive rollbacks entirely.
  • Others enforce migrations that are always backward compatible with at least the previous app version and deploy migrations before service updates.
  • Use of separate DBs per environment and ephemeral DBs for tests is recommended.

Broader views on SQL, ORMs, and DB-centric design

  • Many dislike ORMs and query builders as unnecessary abstractions that are leaky and hard to learn.
  • Several advocate treating the RDBMS (especially Postgres) as the core of the app, using advanced SQL features, with the backend as a thin layer.
  • There is frustration about SQL dialect fragmentation and the difficulty of local testing for nonstandard or cloud-specific SQL engines.