Documentation
Guides

Database

Forge accepts any database connection that satisfies the forge.DB interface — which *sql.DB and pgx adapters both implement. The driver is always your choice.

PostgreSQL — pgx via stdlib shim (recommended)

The recommended choice for most PostgreSQL users. One dependency, near-native pgx speed, compatible with all standard *sql.DB tooling.

terminal
go get github.com/jackc/pgx/v5
main.go
import "github.com/jackc/pgx/v5/stdlib"

db := stdlib.OpenDB(connConfig) // *sql.DB backed by pgx
app := forge.New(forge.Config{DB: db, ...})

PostgreSQL — native pgx pool (maximum performance)

For high-throughput production workloads. Uses forge-pgx, a thin adapter that is a separate module from Forge core (~2.5× faster than lib/pq).

terminal
go get forge-cms.dev/forge-pgx
go get github.com/jackc/pgx/v5
main.go
import (
    forgepgx "forge-cms.dev/forge-pgx"
    "github.com/jackc/pgx/v5/pgxpool"
)

pool, _ := pgxpool.New(ctx, os.Getenv("DATABASE_URL"))
app := forge.New(forge.Config{DB: forgepgx.Wrap(pool), ...})

SQLite

Zero external dependencies. Recommended for single-server deployments, prototyping, and personal sites. This is what forge-cms.dev runs on.

terminal
go get github.com/mattn/go-sqlite3
main.go
import (
    "database/sql"
    _ "github.com/mattn/go-sqlite3"
)

db, _ := sql.Open("sqlite3", "./mysite.db")
app := forge.New(forge.Config{DB: db, ...})
Switching between all three drivers requires changing exactly one value in forge.Config. Nothing else in your codebase changes.

SQLRepo — production SQL repository

SQLRepo[T] is the standard repository implementation backed by forge.DB. It derives the table name automatically or accepts an explicit override.

main.go
// Auto-derived table name: blog_posts
repo := forge.NewSQLRepo[*BlogPost](db)

// Explicit table name
repo := forge.NewSQLRepo[*BlogPost](db, forge.Table("posts"))

m := forge.NewModule((*BlogPost)(nil),
    forge.At("/posts"),
    forge.Repo(repo),
)

SQLRepo uses $N positional placeholders and upserts via ON CONFLICT (id) DO UPDATE.

SeqRepository — streaming results

For large datasets, SQLRepo and MemoryRepo both implement SeqRepository[T] — a lazy streaming interface that avoids loading a full result set into memory.

main.go
if sr, ok := repo.(forge.SeqRepository[*Post]); ok {
    for post, err := range sr.Seq(ctx, opts) {
        // process one at a time
    }
}