Kyrux
Back

Database

Kyrux doesn't import any driver. You add whichever one you need.

1. Add the driver

go get github.com/lib/pq                    # PostgreSQL
go get github.com/go-sql-driver/mysql       # MySQL / MariaDB
go get modernc.org/sqlite                   # SQLite (no CGO)
go get github.com/jackc/pgx/v5/stdlib       # PostgreSQL (pgx)
go get github.com/microsoft/go-mssqldb      # SQL Server
go get github.com/sijms/go-ora/v2           # Oracle (pure Go)

2. Import it with a blank identifier in main.go

import _ "github.com/lib/pq"

3. Configure .env

Each block starting with DB_NAME defines a database. The first one is the default (Use()). Add as many blocks as you need — no numbering, no extra keys.

DB_NAME=principal
DB_ENABLED=true
DB_DRIVER=postgres
DB_DSN=postgres://user:password@localhost:5432/meudb?sslmode=disable

DB_NAME=analytics
DB_ENABLED=true
DB_DRIVER=postgres
DB_DSN=postgres://user:password@localhost:5432/analytics?sslmode=disable

DB_NAME=legado
DB_ENABLED=true
DB_DRIVER=mysql
DB_DSN=user:password@tcp(localhost:3306)/legado

Using the connection in views

Views receive fw via closure in routes.go. Inside the view, pick the database by the name defined in DB_NAME:

func MinhaView(fw *bootstrap.Framework) router.HandlerFunc {
    return func(ctx *router.Context) {
        db          := fw.DB.Use()               // first database from .env (default)
        dbAnalytics := fw.DB.Use("analytics")    // database whose DB_NAME=analytics
        dbLegado    := fw.DB.Use("legado")        // database whose DB_NAME=legado

        posts, err := orm.FromDB[models.Post](db).All()
        stats, err := orm.FromDB[models.Stat](dbAnalytics).All()
        _ = dbLegado
    }
}

Use() with no argument is equivalent to Use("default") and always returns the first database enabled in .env.

Multiple connections at runtime

To add connections outside of .env (e.g. dynamic multi-tenant):

fw.DB.Add("tenant_xyz", "postgres", dsn)
db := fw.DB.Use("tenant_xyz")

Transactions

The callback receives a *database.Tx — it commits if it returns nil, rolls back otherwise (including on panic). The ORM works inside the transaction via orm.FromTx and orm.CreateTx (equivalent to Django's transaction.atomic()):

import "kyrux/core/database"

err := fw.DB.Use().Transaction(func(tx *database.Tx) error {
    pedido := Pedido{Total: 99.90}
    if err := orm.CreateTx(tx, &pedido); err != nil {
        return err // automatic rollback
    }
    // Raw SQL also works — tx embeds *sql.Tx:
    _, err := tx.Exec("UPDATE stats SET total = total + 1")
    if err != nil {
        return err
    }
    return orm.FromTx[Saldo](tx).
        Where("id = ?", 1).
        Update(map[string]any{"valor": 100}) // commit if nil
})

Multi-tenant with schema

// Returns a copy of the connection with the schema set — the original is left unchanged.
db := fw.DB.Use().WithSchema("tenant_abc")

Every query executed with this connection will use tenant_abc.<table> automatically. See the ORM section for full multi-tenant usage.

Supported drivers

Driver Go module Note
postgres github.com/lib/pq
pgx github.com/jackc/pgx/v5/stdlib More modern, but ~15-25% slower than postgres via database/sql (measured)
mysql github.com/go-sql-driver/mysql Also MariaDB
sqlite modernc.org/sqlite No CGO
sqlite3 github.com/mattn/go-sqlite3 Requires CGO
sqlserver github.com/microsoft/go-mssqldb
oracle github.com/sijms/go-ora/v2 Pure Go, no CGO

This page covers SQL only. For MongoDB, Redis, Cassandra, Elasticsearch, and DynamoDB, see the NoSQL page — dedicated, experimental clients, with each database's native API (no single ORM).