Skip to content

Database

CoreAPI connects to two PostgreSQL databases on startup. Your domain doesn't connect to either — it receives a connection passed in from main.go and uses it without knowing where it came from.


The two connections

Both are initialized in pkg/db/db.go via ConnectDB(), called inside db.Init():

Getter Database Used for
db.GetDB() coreapi All CoreAPI-owned domain tables — media, distribution, playback, and any new domain you build
db.GetZooDB() johorzoo Ticketing tables — orders, customers, identity, catalogue, commerce, analytics

The DSN for each is built from environment variables:

# coreapi
DB_HOST, DB_PORT, DB_USER, DB_PASS, DB_NAME

# johorzoo
DB_HOST, DB_PORT, DB_USER, DB_PASS, TICKETING_DB_NAME

Both share the same Postgres instance but are separate databases. johorzoo also sets search_path=johorzoo so all queries scope to that schema.


Assigning a database to your domain

You assign the database in main.go when you call your domain's Setup(). The domain never calls GetDB() itself.

// main.go

mediaroutes.Setup(v1, app, db.GetDB(), storage.GetClient())   // ← coreapi
distributionroutes.Setup(v1, db.GetDB())                       // ← coreapi
playbackroutes.Setup(v1, db.GetDB())                           // ← coreapi

For a domain that needs the ticketing database, pass db.GetZooDB() instead:

yourdomainroutes.Setup(v1, db.GetZooDB())   // ← johorzoo

The domain's Setup() in routes/wire.go receives it as *gorm.DB — a plain GORM connection with no knowledge of which database it is:

// domain/your-domain/routes/wire.go

func Setup(r fiber.Router, db *gorm.DB) {
    cfg := yourdomain.ConfigFromEnv()
    h := handlers.NewHandler(db, cfg)
    registerRoutes(r, h)
}

It flows from there into NewHandler, where it's stored as h.db and used in every handler method:

// domain/your-domain/handlers/handler.go

type Handler struct {
    db  *gorm.DB
    cfg yourdomain.Config
}

func NewHandler(db *gorm.DB, cfg yourdomain.Config) *Handler {
    return &Handler{db: db, cfg: cfg}
}

Your handler methods just call h.db — no awareness of which database it is, no imports from pkg/db:

func (h *Handler) List(c *fiber.Ctx) error {
    var items []yourdomain.YourModel
    h.db.Find(&items)
    return response.OK(c, items)
}

This is what makes the domain variable-name agnostic. Swap db.GetDB() for db.GetZooDB() in main.go and the domain works against the other database with zero changes inside it.


Where the assignment lives today

New-pattern domains are wired from main.go. The ticketing stack (setup.go) follows the same pattern but is called separately — it also uses db.GetZooDB() for all its domains. As domains migrate to the new pattern they move from setup.go into main.go.

When to use which database

If you're building a new domain for PlayTelly features — media, devices, channels, streaming infrastructure — use db.GetDB(). If your domain touches tickets, orders, customers, or events, use db.GetZooDB(). When in doubt, ask.