Skip to main content

Database Connection

In Go, you generally have three layers of abstraction to connect with databases:

LevelDescriptionCommon Packages
🧱 Low-levelUse database/sql directly (standard lib)database/sql, driver like lib/pq, mysql, pgx
βš™οΈ Mid-levelLightweight ORM or query buildersqlx, squirrel, pgxpool
πŸš€ High-levelFull ORM (models, relations, migrations)GORM, Ent, Bun, Prisma Go (coming up)

1. Standard Library: database/sql​

Import Driver & Connect​

import (
"database/sql"
_ "github.com/lib/pq" // PostgreSQL driver
)

dsn := "postgres://user:pass@localhost:5432/mydb?sslmode=disable"
db, err := sql.Open("postgres", dsn)
if err != nil { log.Fatal(err) }
defer db.Close()

Ping & Check Connection​

if err := db.Ping(); err != nil {
log.Fatal("DB unreachable:", err)
}

Query Data​

rows, err := db.Query("SELECT id, name FROM users WHERE active=$1", true)
defer rows.Close()

for rows.Next() {
var id int
var name string
rows.Scan(&id, &name)
fmt.Println(id, name)
}

Query Single Row​

var email string
err := db.QueryRow("SELECT email FROM users WHERE id=$1", 1).Scan(&email)

Exec (INSERT/UPDATE/DELETE)​

res, err := db.Exec("UPDATE users SET name=$1 WHERE id=$2", "Fee Fight", 1)
affected, _ := res.RowsAffected()

Transactions​

tx, _ := db.Begin()
_, err := tx.Exec("INSERT INTO logs(message) VALUES($1)", "hello")
if err != nil {
tx.Rollback()
return
}
tx.Commit()

DatabaseDriverImport Path
PostgreSQLlib/pq or jackc/pgx/stdlib_ "github.com/lib/pq" or _ "github.com/jackc/pgx/v5/stdlib"
MySQL / MariaDBgo-sql-driver/mysql_ "github.com/go-sql-driver/mysql"
SQLitemodernc.org/sqlite (pure Go)_ "modernc.org/sqlite"
SQL Serverdenisenkom/go-mssqldb_ "github.com/denisenkom/go-mssqldb"

⚑ pgx is increasingly preferred over lib/pq for Postgres β€” it’s faster, supports more features, and can be used standalone or with database/sql.


3. sqlx β€” Upgraded database/sql​

https://github.com/jmoiron/sqlx

Adds struct mapping, named queries, and convenience methods.

import "github.com/jmoiron/sqlx"

db, _ := sqlx.Connect("postgres", dsn)

// Named parameters
rows, _ := db.NamedQuery("SELECT * FROM users WHERE age >= :age", map[string]interface{}{"age": 18})

// Struct mapping
type User struct { ID int `db:"id"`; Name string `db:"name"` }
var users []User
db.Select(&users, "SELECT id, name FROM users")

βœ… Keeps control like database/sql βœ… Zero magic βš™οΈ Great for microservices or APIs


4. pgx β€” Native Postgres Driver​

https://github.com/jackc/pgx

Faster + more feature-rich (copy, notifications, pools, etc.)

import "github.com/jackc/pgx/v5/pgxpool"

pool, _ := pgxpool.New(context.Background(), dsn)
defer pool.Close()

rows, _ := pool.Query(ctx, "SELECT id, name FROM users")
for rows.Next() {
var id int
var name string
rows.Scan(&id, &name)
}

βœ… Best for PostgreSQL-heavy backends βœ… Built-in connection pool βœ… Fine-grained control (batching, COPY, notifications)


https://gorm.io

Setup​

import (
"gorm.io/gorm"
"gorm.io/driver/postgres"
)

dsn := "host=localhost user=me password=pass dbname=mydb sslmode=disable"
db, err := gorm.Open(postgres.Open(dsn), &gorm.Config{})

Model & Migrate​

type User struct {
ID uint `gorm:"primaryKey"`
Name string
Email string `gorm:"uniqueIndex"`
}
db.AutoMigrate(&User{})

CRUD​

db.Create(&User{Name: "Fee", Email: "fee@fight.dev"})
var u User
db.First(&u, "email = ?", "fee@fight.dev")
db.Model(&u).Update("Name", "Fee Fight")
db.Delete(&u)

βœ… ORM (relations, hooks, migrations) βœ… Very active community βš™οΈ Slightly heavier, but solid for APIs and SaaS apps


6. Ent β€” Type-Safe ORM (by Facebook)​

https://entgo.io

Ent generates Go code (schema β†’ Go structs β†’ SQL migrations).

go get entgo.io/ent/cmd/ent
go run entgo.io/ent/cmd/ent init User

Schema example:

// ent/schema/user.go
func (User) Fields() []ent.Field {
return []ent.Field{
field.String("name"),
field.String("email").Unique(),
}
}

Generate code:

go generate ./ent

Usage:

client, _ := ent.Open("postgres", dsn)
defer client.Close()

u, _ := client.User.Create().SetName("Fee").SetEmail("fee@fight.dev").Save(ctx)
fmt.Println(u.ID)

βœ… Type-safe queries (compile-time check) βœ… Generates migrations βš™οΈ Slight learning curve, best for larger apps


7. Bun β€” Modern ORM (Fast + Familiar)​

https://bun.uptrace.dev

Built on pgx, supports PostgreSQL, MySQL, SQLite.

import (
"github.com/uptrace/bun"
"github.com/uptrace/bun/driver/pgdriver"
)

sqldb := sql.OpenDB(pgdriver.NewConnector(pgdriver.WithDSN(dsn)))
db := bun.NewDB(sqldb, pgdialect.New())

type User struct {
ID int64 `bun:",pk,autoincrement"`
Name string
}

db.NewInsert().Model(&User{Name: "Fee"}).Exec(ctx)

βœ… Fast, active, SQL-first ORM βœ… Integrates with metrics/logs easily βœ… Feels like GORM but lighter


8. NoSQL Options​

DatabasePackageNotes
MongoDBgo.mongodb.org/mongo-driverOfficial driver
Redisgithub.com/redis/go-redis/v9Great for caching, pub/sub
Cassandragithub.com/gocql/gocqlMature driver
Elasticsearchgithub.com/elastic/go-elasticsearch/v8Official client

Example Mongo snippet:

client, _ := mongo.Connect(ctx, options.Client().ApplyURI("mongodb://localhost:27017"))
col := client.Database("test").Collection("users")
col.InsertOne(ctx, bson.M{"name": "Fee"})

9. Connection Pooling​

  • database/sql already pools connections internally.

  • pgxpool (for Postgres) gives explicit control.

  • Tune with:

    db.SetMaxOpenConns(10)
    db.SetMaxIdleConns(5)
    db.SetConnMaxLifetime(time.Hour)

10. Migration Tools​

ToolCommandDescription
golang-migratemigrate -path db/migrations -database postgres://... upCLI + Go API
gooseSimple, SQL-based migrations
gormigrateFor GORM ORM projects
atlasModern schema management for Ent / SQL
ScaleStackWhy
🧩 Small APIdatabase/sql + sqlxLightweight & fast
πŸš€ Mid-size servicepgx or BunStrong performance + dev ergonomics
🧠 Full app / SaaSGORM or EntRich ORM + migration system
⚑ Data-intensive / custom SQLpgxpool + query builderMax control