#5354·vendure

T3 decision needed: which Nest lifecycle hook owns startup initialization (#3638)

Author: biggamesmallworldCreated Sep 10, 2026Updated Sep 10, 2026

Raised from a classification audit of the open PR queue. #3638 has carried T3: Systemic since July 2025. The decision it is waiting on was never queued anywhere, so this issue queues it.

T3 decision needed: which Nest lifecycle hook owns startup initialization

The local fix. #3638 swaps the two hooks. ConfigModule moves from onApplicationBootstrap to onModuleInit, so strategies and configurable operations initialize before any other module's onModuleInit. InitializerService moves the other way, from onModuleInit to onApplicationBootstrap.

On master the two sit the opposite way round: InitializerService.onModuleInit runs the ordered data initialization (zones, global settings, sellers, channels, roles, administrators, shipping methods, tax rates, stock locations, then InitializerEvent), while ConfigModule.onApplicationBootstrap initializes strategies. A strategy's init() therefore runs after the data initializers, and a plugin service cannot use an initialized strategy from its own onModuleInit.

The systemic implication. Two patterns from systemic-patterns.md.

Pattern 3, changing default behaviour for existing installs: every install's startup order changes after an upgrade, and a plugin that currently relies on running before the default channel exists, or on strategies being uninitialized during onModuleInit, behaves differently with no way to know.

Pattern 7, resolving ambiguity by picking one interpretation: merging it blesses the contract that strategy init() always precedes any module's onModuleInit. That becomes a guarantee plugin authors write against, and unwinding it later is a breaking change.

Options.

  1. Merge the swap as it stands. Fixes the ordering properly and publishes the guarantee. Existing plugins that depend on the current order break silently on upgrade.
  2. Keep master's order and document it as the contract. No upgrade risk, but plugin authors keep hitting the case that motivated the PR.
  3. Publish the guarantee behind a config flag, defaulting to the current order. Follows the standing policy that a default behaviour change must be opt-in, at the cost of two supported startup orders.

Recommendation. The question is whether the ordering guarantee is worth a silent startup change for existing installs. I have no view on which way that should go, which is why this is here rather than in a pull request.

Status. The PR is decision-ready, not blocked on work. @grolmus completed the call-site audit and added a regression test (packages/core/e2e/lifecycle-init-order.e2e-spec.ts) in May 2026. The diff is three files. The motivating PR #3222 was closed unmerged, which removes the urgency but not the question.