Back to basics: Writing an application using Go and PostgreSQL

This page summarizes the projects mentioned and recommended in the original post on news.ycombinator.com

Our great sponsors
  • Scout APM - Less time debugging, more time building
  • OPS - Build and Run Open Source Unikernels
  • SonarQube - Static code analysis for 29 languages.
  • litestream

    Streaming replication for SQLite.

    I had the same objection to SQLite, and then I heard about Litestream, and it won me over.[0]

    Litestream watches your SQLite database and then streams changes to a cloud storage provider (e.g., S3, Backblaze). You get the performance and simplicity of writing SQLite to the local filesystem, but it's syncing to the cloud. And the cool part is that you don't have to change any of your application code to do it - as far as your app is concerned, it's writing to a local SQLite file.

    I wrote a little log uploading utility for my business that uses Litestream, and it's been fantastic.[1] It essentially carries around its data with it, so I can deploy my app to Heroku, blow away the instance and then launch it on fly.io, and it pops up with the exact same data.[2]

    I'm currently in the process of rewriting an open-source AppEngine app to use SQLite + Litestream instead of Google Firestore.[2] It's such a relief to get away from all the complexity of GCP and Firestore and get back to simple SQLite.

    [0] https://litestream.io/

    [1] https://mtlynch.io/litestream/

    [2] https://asciinema.org/a/I2HcYheYayeh7aHj23QSY9Vyf/embed?size...

    [3] https://github.com/mtlynch/whatgotdone/pull/639

  • pgxtutorial

    Fair criticism. I'm the author, and I hate using interfaces like this, but didn't comment on it probably because I got used to it for this kind of thing.

    The only reason why I defined inventory.DB (https://github.com/henvic/pgxtutorial/blob/main/internal/inv...) is to be able to test. Otherwise, I'd have skipped it.

    I haven't read your article yet, but will do so later and get back to this subject and tell my opinion by the end of the day (on vacation, and need to hurry to catch the train!).

  • Scout APM

    Less time debugging, more time building. Scout APM allows you to find and fix performance issues with no hassle. Now with error monitoring and external services monitoring, Scout is a developer's best friend when it comes to application development.

  • pq

    Pure Go Postgres driver for database/sql

    The article mentions that lib/pq is "effectively in maintenance mode". This surprised me, I've never had problems with it, and looking at the commits on github [1] it seems far from inactive.

    [1] https://github.com/lib/pq/commits/master

  • sqlc

    Generate type-safe code from SQL

    Great article! These days, though, I find myself reaching for sqlc whenever I need to access Postgres from Go. My experience with the project has been excellent: I get type-safe APIs and control over exactly which queries are executed without much fuss.

    https://sqlc.dev/

  • pgx

    PostgreSQL driver and toolkit for Go

    The way it parses dates using Unix time causes issues when you compare the values returned due to Go setting the location property:

    https://github.com/jackc/pgx/issues/863

    pgx doesn't seem to handle reconnects the same way lib/pg does, but I haven't tested this recently: https://github.com/jackc/pgx/issues/672

  • whatgotdone

    A tool for sharing weekly task updates with teammates.

    I had the same objection to SQLite, and then I heard about Litestream, and it won me over.[0]

    Litestream watches your SQLite database and then streams changes to a cloud storage provider (e.g., S3, Backblaze). You get the performance and simplicity of writing SQLite to the local filesystem, but it's syncing to the cloud. And the cool part is that you don't have to change any of your application code to do it - as far as your app is concerned, it's writing to a local SQLite file.

    I wrote a little log uploading utility for my business that uses Litestream, and it's been fantastic.[1] It essentially carries around its data with it, so I can deploy my app to Heroku, blow away the instance and then launch it on fly.io, and it pops up with the exact same data.[2]

    I'm currently in the process of rewriting an open-source AppEngine app to use SQLite + Litestream instead of Google Firestore.[2] It's such a relief to get away from all the complexity of GCP and Firestore and get back to simple SQLite.

    [0] https://litestream.io/

    [1] https://mtlynch.io/litestream/

    [2] https://asciinema.org/a/I2HcYheYayeh7aHj23QSY9Vyf/embed?size...

    [3] https://github.com/mtlynch/whatgotdone/pull/639

  • dockertest

    Write better integration tests! Dockertest helps you boot up ephermal docker images for your Go tests with minimal work.

    Dockertest makes it really easy to test Go+Postgresql projects. I use it a lot.

    https://github.com/ory/dockertest

  • OPS

    OPS - Build and Run Open Source Unikernels. Quickly and easily build and deploy open source unikernels in tens of seconds. Deploy in any language to any cloud.

  • pggen

    Generate type-safe Go for any Postgres query. If Postgres can run the query, pggen can generate code for it.

    You might like pggen (I’m the author) which only supports Postgres and pgx. https://github.com/jschaf/pggen

    pggen occupies the same design space as sqlc but the implementations are quite different. Sqlc figures out the query types using type inference in Go which is nice because you don’t need Postgres at build time. Pggen asks Postgres what the query types are which is nice because it works with any extensions and arbitrarily complex queries.

  • sqlx

    🧰 The Rust SQL Toolkit. An async, pure Rust SQL crate featuring compile-time checked queries without a DSL. Supports PostgreSQL, MySQL, SQLite, and MSSQL. (by launchbadge)

    >I don’t need orm, just automated mapping”

    Check out https://github.com/launchbadge/sqlx#sqlx-is-not-an-orm for an alternative approach.

  • go

    The Go programming language

    One should be careful about these mega-interfaces that define an entire subsystem of your application (DB in this case). They are very painful to maintain, and add almost no value. Interfaces should always be defined by the consumer of the interface, not by the producer. And interfaces should never be used until there is a clear need. CodeReviewComments covers the basics: https://github.com/golang/go/wiki/CodeReviewComments#interfa...

    I wrote an insanely long rant about this, but it was too long for HN. So I put it on my blog instead: https://jrock.us/posts/go-interfaces/

  • go-mockgen-tool

    Go/Golang mock generation for interfaces via code generation

    For testing I wrote https://github.com/jamesrr39/go-mockgen-tool to generate mock implementations of a given interface. It's a different approach from the normal reflect and interface{}... heavy libraries. Might be interesting!

  • impl

    impl generates method stubs for implementing an interface. (by josharian)

    Looks interesting! Reminds me impl[0], which comes bundled with `vscode-golang`.

    [0]: https://github.com/josharian/impl

NOTE: The number of mentions on this list indicates mentions on common posts plus user suggested alternatives. Hence, a higher number means a more popular project.

Suggest a related project

Related posts