Database
PostgreSQL via pgx, with embedded migrations and a repository pattern.
HAMR uses pgx as the database driver, sqlx for typed queries, and golang-migrate for migrations. The connection layer is in pkg/db and handles retries, pooling, and migration runs for you.
Connecting
package db
import (
"context"
"github.com/FyrmForge/hamr/pkg/db"
)
func ConnectContext(ctx context.Context, url string) (*db.DB, error) {
return db.Connect(ctx, db.Config{
URL: url,
MaxOpenConns: 25,
MaxIdleConns: 5,
RetryAttempts: 5,
})
}db.Connect retries with exponential backoff so the app can wait for Postgres to come up — perfect for Docker Compose setups where the database might not be ready yet.
Migrations
SQL migrations live in internal/db/migrations/ with a sequential numbering scheme. Each migration has matching .up.sql and .down.sql files.
CREATE TABLE users (
id TEXT PRIMARY KEY,
email TEXT UNIQUE NOT NULL,
password TEXT NOT NULL,
name TEXT NOT NULL,
created_at TIMESTAMPTZ NOT NULL DEFAULT NOW()
);DROP TABLE users;Migrations are embedded into the binary via embed.FS and run automatically on startup:
import "embed"
//go:embed migrations/*.sql
var migrationFS embed.FS
func AutoMigrate(database *db.DB) error {
return database.MigrateFS(migrationFS, "migrations")
}Repository pattern
Data access lives in internal/repo/. The package defines a Store interface, and concrete implementations live in subpackages (e.g. internal/repo/postgres).
package repo
import "context"
type Store interface {
BookRepo
UserRepo
}
type BookRepo interface {
All(ctx context.Context) ([]Book, error)
Get(ctx context.Context, id string) (*Book, error)
Create(ctx context.Context, book *Book) error
Update(ctx context.Context, book *Book) error
Delete(ctx context.Context, id string) error
}package postgres
import (
"context"
"github.com/yourname/myapp/internal/repo"
)
func (s *Store) All(ctx context.Context) ([]repo.Book, error) {
var books []repo.Book
err := s.db.SelectContext(ctx, &books,
"SELECT id, title, author, created_at FROM books ORDER BY created_at DESC")
return books, err
}