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
.sqlfiles 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.