# ADR-003: BeforeStart Hooks for Dependency Injection Wiring **Status:** Accepted **Date:** 2026-03-18 ## Context After all components have been initialised (`OnInit`), some wiring cannot be expressed at construction time because it requires the initialised state of multiple components simultaneously. For example, an HTTP server may need to register routes that reference handler functions which themselves hold references to a database client — but the database client only becomes ready after `OnInit` runs, which is after all components are constructed. One alternative is to wire everything in `main` before calling `Run`, but that requires `main` to know the internal structure of every component, defeating encapsulation. Another alternative is to wire in `OnStart`, but at that point other components may already be running and the window for setup errors is narrower. ## Decision `Launcher.BeforeStart(hooks ...Hook)` registers functions of type `func() error` that are called after all `OnInit` calls succeed and before any `OnStart` call begins. Hooks are called in registration order. If any hook returns an error, `Run` returns that error immediately without proceeding to `OnStart`. `Hook` is a plain function type with no parameters beyond what closures capture. This allows hooks to close over the components they wire, without `launcher` needing to know anything about those components beyond the `Component` interface. ## Consequences - Dependency injection wiring is expressed as closures registered with `BeforeStart`, keeping `main` as the composition root without exposing internals. - All `OnInit` guarantees (connections open, ports bound, resources allocated) are satisfied before any hook runs — hooks can safely call methods on initialised components. - Hook errors abort the lifecycle cleanly. No components have started yet, so no cleanup of running services is needed (though `OnStop` will still run for any components that successfully ran `OnInit`, consistent with ADR-001's behaviour when `OnStart` fails). - The pattern scales to any number of wiring steps without adding methods to the `Component` interface.