Forge
1.x
Docs/Forge/Lifecycle and DI
Open

Deprecated

Use Grove instead.

Reading2 min
Updated31 Jul 2026
Sourcev1/extensions/database/lifecycle-di.mdx

Preferred Pattern01

Use constructor registration and type-based injection as the default style.

// Register constructors
forge.ProvideConstructor(c, func(db *Database, logger forge.Logger) *UserService {
    return &UserService{db: db, logger: logger}
})
// Resolve by type (no string keys needed)
userService, err := forge.InjectType[*UserService](c)

eventBus, _ := vessel.InjectType[interfaces.EventBus](app.Container())

Extension Registration Graph02

database.Extension.Register(app) performs:

  1. configuration load and validation

  2. eager registration of *DatabaseManager

  3. registration of default Database accessor

  4. registration of type-specific accessor for default DB type:

    • SQL default -> *bun.DB

    • Mongo default -> *mongo.Client

    • Redis default -> redis.UniversalClient

Key Service Identifiers03

Constants in package:

  • database.ManagerKey

  • database.DatabaseKey

  • database.SQLKey

  • database.MongoKey

  • database.RedisKey

Primary resolution path in modern code should still be type-based helpers.

Runtime Lifecycle04

  • DatabaseManager.Start(ctx):

    • marks manager started

    • opens all registered databases (idempotent)

  • DatabaseManager.Stop(ctx):

    • marks manager stopped

    • closes all databases

  • DatabaseManager.Health(ctx):

    • fails if any registered database is unhealthy

Extension-level lifecycle methods only mark extension started/stopped; manager owns connection lifecycle.

By Type + Name (Best for multi-db)

manager, _ := database.GetManager(app.Container())
primary, _ := manager.SQL("primary")
analytics, _ := manager.Mongo("analytics")
cache, _ := manager.Redis("cache")

Through Helpers

primary, _ := database.GetSQL(app.Container(), "primary")
cache, _ := database.GetRedis(app.Container(), "cache")

App-Level Convenience

primary, _ := database.GetSQLFromApp(app, "primary")

When Registering Your Own Services06

Inject *database.DatabaseManager and resolve named DBs inside constructors. This keeps your service constructors explicit and avoids implicit assumptions about default DB type.