dbtpl offers five install routes and the Go one does not install a release
Command line tool to generate idiomatic Go code for SQL databases supporting PostgreSQL, MySQL, SQLite, Oracle, and Microsoft SQL Server
At a glance
- What is it?
- dbtpl introspects a database schema or a single query and renders Go templates against what it finds, and its five documented install routes are maintained in five different places, one of which builds from the branch rather than from a tag.
- Who is it for?
- dbtpl is a reasonable fit for a Go shop that wants its database layer written in one dialect and regenerated on a schedule, with PostgreSQL as the only engine that gets enums and custom types.
- Can I use it commercially?
- Yes. MIT is a permissive licence: you can use, modify and sell software built on it, as long as you keep its copyright and licence notices.
- Is it still maintained?
- Yes. The repository last received commits 68 days ago.
- What is it written in?
- Mainly Go, according to GitHub's language statistics.
Answers come from the project's GitHub data, last synced on November 14, 2026, and from our analysis. They are not legal advice.
Star history
- xo/dbtpl3,899 ★ · +0
| Repository | 2026-09-24 | 2026-11-14 |
|---|---|---|
| xo/dbtpl | 3.9k | 3.9k |
0 Stars in the last 51 days, measured from the daily GitHub snapshot. Compare with other projects
Editorial analysis
The Go install route builds from the branch, not from a release
Five install routes are offered and they are not interchangeable. The release route asks you to download a platform archive, extract the dbtpl or dbtpl.exe file from a .tar.bz2 or a .zip, and put the executable somewhere on your $PATH. The Go route asks for one line:
# install latest dbtpl version
$ go install github.com/xo/dbtpl@latestThat second command does not fetch a release. It builds from the module's default branch, which was pushed on 8 September 2026, while the newest published release is v1.0.2 from 24 May 2024. A reader who follows the Go instructions and a reader who follows the release instructions therefore ends up running different code, and the file never says so. The gap matters more for the Go route than it would for a packaged download, because go install compiles the tool locally: your own toolchain has to satisfy whatever go.mod asks for, and that file declares a go directive of 1.26. The prebuilt archives ask none of that of you.
The Arch example is pinned to 0.4.4-1 and the tags read 1.0.2
The Arch Linux instructions ship with a worked example, and the version inside it is old. The makepkg output reads:
# clone package repo and make/install package
$ git clone https://aur.archlinux.org/dbtpl.git && cd dbtpl
$ makepkg -si
==> Making package: dbtpl 0.4.4-1 (Sat 11 Nov 2023 02:28:28 PM WIB)
==> Checking runtime dependencies...
==> Checking buildtime dependencies...
==> Retrieving sources...
...That is 0.4.4-1, dated 11 November 2023, which is below 1.0. Both tags that exist now postdate it: 1.0.1 from December 2023 and 1.0.2 from May 2024. The same shape of drift applies to the other two package managers. Homebrew is reached through the xo/xo tap rather than a formula in the main repository, and Scoop needs a manifest this project does not contain. Three of the five routes are therefore maintained somewhere other than here, and the README gives no way to tell which version any of the four would hand you today. The one route the project fully controls is also the one with the least said about it, three numbered steps and no checksum, no signature and no version flag to run afterwards.
The quickstart opens a heredoc it never closes
The third quickstart example is the one to read carefully, because as printed it cannot finish:
# Generate code from a custom SQL query for Postgres
$ dbtpl query postgres://user:pass@host/dbname -M -B -2 -T AuthorResult << ENDSQL
SELECT
a.name::varchar AS name,
b.type::integer AS my_type
FThe redirect announces the delimiter ENDSQL, and the block ends on a line holding the single letter F. Nothing in between is ENDSQL, so a shell reading this waits for a terminator that never arrives and the query never reaches the program at all. Whether that F is a stray keystroke or the remains of something else makes no difference to the reader, who has no delimiter to type. The delimiter is also unquoted, which means the shell expands variables, command substitutions and backticks inside the SQL before dbtpl sees it, so a query carrying a dollar sign is a second thing to watch. The two examples above it in the same block, the plain Postgres call and the Microsoft SQL one with a custom template directory, are both complete and runnable as written.
The published option list stops partway through a flag name
The options reference is a paste of dbtpl --help-long, and it ends mid token. The final line shown is -f, --suffi, the suffix option of the query command, with no completion and no explanation. Above it the same command shows -s, --schema for a database schema name and -t, --template, whose accepted values are spelled out in full as createdb, dot, go, json and yaml, defaulting to go. That one flag is the widest thing in the tool, covering database creation scripts, Graphviz output and JSON or YAML definitions alongside Go models, and it maps one to one onto the output kinds promised near the top of the file. The quickstart passes -M, -B, -2 and -T, none of which appears in the visible part of the list. The program can always be asked directly with --help-long or --help-man, so what is missing here is documentation rather than a capability.
PostgreSQL alone is checked for enums and custom types
The prose and the matrix do not say quite the same thing. The prose says dbtpl can generate types for tables, enums, stored procedures and custom SQL queries for PostgreSQL, MySQL, Oracle, Microsoft SQL Server and SQLite3, which reads as one uniform capability spread across five engines. The table beneath it is more specific. Models, primary keys, foreign keys, indexes, stored procs and functions are checked across all five columns. ENUM types are checked only under PostgreSQL. Custom types are checked only under PostgreSQL. So an enum outside PostgreSQL, or a custom type anywhere but PostgreSQL, sits outside what the matrix claims, and the sentence above it gives no hint of the limit. The prose also leaves functions out entirely even though the matrix checks them in every column. Both sit within a screen of each other in the same file, and the table is the one anybody planning a migration would want to trust.
The summary promises idiomatic Go and the note walks it back
The one line summary calls this a tool to generate idiomatic Go code for SQL databases. The README adds a note that pulls the other way: while the code generated by dbtpl is production quality, it is neither the goal nor the intention for dbtpl to be a silver bullet, nor meant to eliminate the manual authoring of SQL and Go code. Read strictly, that concedes hand written queries stay in the picture, which is the opposite of what a generator advertises. Scope is narrow in a second way too, since the supported languages section says only Go is supported and that support for other languages is possible but not currently planned. Five database engines, five output formats and one output language, with the roadmap explicitly closed on the language axis and no issue tracking that in the file.
The module list carries an interpreter, a formatter and the author's own framework
go.mod asks for considerably more than database drivers. Alongside one driver per engine sit a template library, a YAML package, a glob and inflector pair, and three entries with a different character: github.com/traefik/yaegi, github.com/xo/ox and mvdan.cc/gofumpt. The README never says what the first of those is for, and an interpreter sitting in the dependency block of a code generator is the kind of entry a reader would want explained before trusting the output. The second is the author's own command line framework, pinned not to a release but to a pseudo version dated 22 June 2026, so the tool tracks a moving commit of its author's library rather than a tagged one. The third is a Go formatter, also a direct requirement, next to golang.org/x/tools. DSN parsing goes through github.com/xo/dburl, which is why the mssql:// scheme in the quickstart works next to the drivers' own prefixes.
The tree shows the generated output first and hides the examples
The root of the tree is a small map of how this project works on itself. main.go and cmd/ hold the command, internal/ the implementation, loader/ the template loading, and templates/ the base templates the README calls generic and not suitable for every organisation. Then come models/ and types/, which are the artefacts the tool produces. gen.sh and build.sh sit at the top level beside them, so the project drives its own generation from a script, and a Go formatter is a direct requirement in the module list, which is where generated Go would get tidied before it was committed. One entry is named _examples/, which begins with the character Go requires in order to keep a directory out of the build, so the sample material is deliberately invisible to the toolchain. The practical consequence is that a reader scanning the tree meets the finished output before the templates that shaped it, and the examples only after looking somewhere the compiler never looks.
Editorial conclusion
dbtpl is a reasonable fit for a Go shop that wants its database layer written in one dialect and regenerated on a schedule, with PostgreSQL as the only engine that gets enums and custom types. Check three things before committing to it: whether the output is meant to replace hand written queries, which the README's own note says it is not; whether the template flag is enough for the formats you need, since the published option list ends mid flag; and which version your package manager will actually hand you, because the Arch example on file is 0.4.4-1 while the newest tag is 1.0.2. Expect to run dbtpl --help-long rather than trust the pasted options.
Frequently asked questions
What does dbtpl generate from a database schema?
Models, primary keys, foreign keys, indexes, stored procedures and functions for PostgreSQL, MySQL, Oracle, Microsoft SQL Server and SQLite3. Enum types and custom types are checked only in the PostgreSQL column of the support matrix.
Which output formats can dbtpl produce besides Go code?
The template flag takes createdb, dot, go, json or yaml and defaults to go, which covers database creation scripts, Graphviz diagrams and JSON or YAML definitions alongside generated Go.
How do you install dbtpl on Windows?
Either download a release archive, extract dbtpl.exe and put it on your %PATH%, or install Scoop first with irm get.scoop.sh | iex and then run scoop install dbtpl. The PowerShell route also needs Set-ExecutionPolicy RemoteSigned -Scope CurrentUser for the first remote script.
Does dbtpl generate anything other than Go?
No. Only Go is supported, and support for other languages is described as possible but not currently planned, so a non Go caller has no path through this tool.
How does dbtpl handle a custom SQL query instead of a whole schema?
In query mode it parses the query you supply and looks for related tables in the database so the generated code stays type safe. The quickstart runs that mode with the flags -M, -B, -2 and -T alongside the name AuthorResult.
Official sources
Add this badge to your README
If you maintain this project, the badge below links readers to this analysis and shows its maintenance status from the daily GitHub snapshot. Paste the markdown into your README; add ?metric=license or ?metric=stars to the image URL for a different field.
[](https://hysenlabs.com/projects/xo-dbtpl)Star history chart for your README
[](https://hysenlabs.com/projects/xo-dbtpl)Was this useful?