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.