Files
agentic-dev/docs/decisions/adr-008-per-feature-di-containers.md
Danijel Martinek f77e6ea881 chore(template): clean-slate template snapshot from bb4a0c7
Curated, product-agnostic snapshot of the post-story-04 tree: demo
content deleted, auth-only reference feature, web-next shell, all gates
green. Product-specific docs, ADRs 027-029, PRDs/epics/archive, editor
library traces, and product naming are curated out; generic template
repairs (coverage provider devDeps, root test:coverage script, live
lint fixes, root-only release-please) are kept. See TEMPLATE.md for
provenance, curation list, and usage.

Co-Authored-By: Claude Fable 5 <noreply@anthropic.com>
Claude-Session: https://claude.ai/code/session_016j8z4VHjedXDTjEDNg7qHK
2026-07-12 20:40:54 +02:00

1.4 KiB

ADR-008: Per-Feature InversifyJS Containers

Status: Accepted Date: 2026-05-04

Context

The original template used a single shared InversifyJS Container in packages/core/src/di/. As the number of features grows, the container becomes a point of coordination: adding a symbol requires modifying shared code, and tests that mock one feature risk breaking others.

Decision

Each feature owns its own Container and symbol table. No shared DI state. Tests rebind per feature in isolation. Apps boot by calling bindProduction*() for each feature independently.

Example:

// packages/blog/src/di/container.ts
export const container = createContainer();

// packages/blog/tests/feature.test.ts
beforeEach(() => {
  rebindRepository(new TestRepository());
  // Only blog's container is affected
});

Consequences

  • Zero cross-feature DI coupling — each feature's test can mock its repos without coordination
  • Symbol collisions impossible — each feature has its own ARTICLES_REPOSITORY symbol
  • Shared services (if needed) are explicitly bound in each feature that uses them
  • Apps must boot each feature's container on startup

Alternatives Considered

  • Single shared container: Simpler upfront, becomes a bottleneck and test coordination point
  • Function injection (no DI): Avoids framework overhead, but loses the scaling benefits of DI