Bob
A Go toolkit for your database · type-safe queries, generated from the schema you already have.
In Go, you usually pick between two extremes. Raw query strings are fast, but a typo only blows up at runtime. A magic ORM is safe, but opaque. Bob is a third option: Go packages that generate fully type-safe queries from your own database, checked by the compiler, with no magic.
A database toolkit, not magic
- Fluent query builder · dialect-correct for Postgres, MySQL, and SQLite.
- Typed results · rows scanned straight into your Go structs.
- Generated models + factories · type-safe, from your existing schema.
So what is Bob? A set of Go packages for your database, adopted one layer at a time. Start with a fluent query builder, dialect-correct for Postgres, MySQL, and SQLite, so you can't build an invalid query. An executor scans results straight into your Go structs. And a generator reads your schema and writes type-safe models, plus factories. The principle: convenience, not magic.
Start where you are: the query builder
// Postgres · fluent, dialect-correct, no model yet
psql.Select(
sm.From("users"),
sm.Where(psql.Quote("age").GTE(psql.Arg(21))),
)
Each argument is a query mod · a
From, a Where, and so on.
You don't have to start with code generation. Bob's query builder is fluent and dialect-correct, and you can use it right away. Every argument is a query mod: a From, a Where, and so on. On its own, though, the builder can't check your column names.
Point Bob at your database
# inspects your live schema · writes a
# type-safe models package, plus factories
PSQL_DSN=postgres://user:pass@host:port/dbname \
go run github.com/stephenafamo/bob/gen/bobgen-psql@latest
One command · and the same raw queries become type-safe, compile-checked Go.
Now the first win. Point Bob at a database you already have. One command: set the connection string, then go run the Postgres generator. Bob inspects your live schema and writes a fully type-safe models package, plus factories for your tests. There's a matching generator for MySQL and for SQLite.
The same query, now type-safe
// builder query · valid, but not type-checked
psql.Select(
sm.Where(psql.Quote("age").GTE(psql.Arg(21))),
)
// generated · every name checked by the compiler
models.Users.Query(
models.SelectWhere.Users.Age.GTE(21),
).All(ctx, db)
Rename a column, regenerate · every wrong query fails to compile.
Here's the payoff, the same query as before. The generated version is type-safe: every table and column is a real Go symbol, checked by the compiler. Rename a column, regenerate, and every wrong query fails to compile, caught before you ship, not in production.
Test data, generated too
// the posts and users it needs are created too
comments, err := f.NewComment().CreateMany(ctx, db, 10)
FactoryBot-style factories · built from the same schema.
Generation also gives you factories, inspired by Ruby's FactoryBot. Ask for ten comments and Bob creates them, wiring up the posts and users they depend on. Realistic test data from the same schema, without writing fixtures by hand.
From raw queries to type-safe, no magic
- Query builder · fluent, dialect-correct.
- Generated models · type-safe, from your schema.
- Factories · realistic test data for free.
- Progressive · adopt one layer at a time.
bob.stephenafamo.com
That's the arc. A fluent query builder, type-safe models generated from your own database, and factories for your tests, adopted one layer at a time, with no magic. It works with Postgres, MySQL, and SQLite. Start here: bob dot stephenafamo dot com.


















