Skip to content

ADR-018 Platform Starter Dependency Model

Status: Accepted Date: 2026-06-19


Context

The platform provides shared capabilities (CQRS, security, outbox, observability, etc.).

We must define how these capabilities are consumed by microservices without:

  • Tight coupling
  • Manual configuration duplication
  • Infrastructure leakage into business code

Decision

We adopt a Spring Boot Starter-based modular dependency model.


1. Starter-Based Architecture

Each platform capability is exposed as a:

```text id="p1k9lm" spring-boot-starter-*

Examples:

* starter-api
* starter-security
* starter-mediator
* starter-outbox
* starter-inbox
* starter-observability

---

# 2. Dependency Rule

Microservices MUST ONLY depend on starters.

They MUST NOT depend on internal platform modules directly.

---

# 3. Auto-Configuration Rule

Each starter MUST provide:

* AutoConfiguration classes
* Conditional beans
* Default implementations
* Override capability

---

# 4. Composition Rule

Services compose behavior via dependency inclusion:

```xml id="d1k9lm"
starter-security
starter-outbox
starter-mediator


5. Override Rule

Services MAY override:

  • beans
  • configurations
  • behaviors

without modifying platform code.


Consequences

Positive

  • Clean separation between platform and services
  • High reusability
  • Easy service bootstrap
  • Strong modular design

Negative

  • Requires disciplined starter design
  • Debugging auto-config issues can be complex

  • ADR-007 Platform Library Strategy
  • ADR-014 CI/CD Strategy

Amendment (2026-07-08)

Status: Accepted (amendment). Raised during Feature 14.5 (Avro Schema Governance Reconciliation, docs/tasks/sprint-14-testing-and-hardening/14.5-avro-schema-governance-ruling.md), where code-review flagged that platform-event-contracts had been added as a direct, non-starter dependency to 6 additional services (test-scope) and asked tech-lead to rule on whether this violates Section 2's unscoped "MUST ONLY depend on starters" text. Ruled on by tech-lead. Does not supersede or rewrite the Decision above; adds one explicit, bounded carve-out so this question is not re-litigated by a future agent.

A1. The Dependency Rule targets runtime infrastructure coupling, not contract-definition modules

Section 2's "Microservices MUST ONLY depend on starters... MUST NOT depend on internal platform modules directly" exists to prevent the three harms named in this ADR's own Context: tight coupling to platform internals, manual configuration duplication, and infrastructure leakage into business code. Those harms are properties of modules like platform-core that carry business logic, bean wiring, AutoConfiguration, and behavior a service would otherwise have to reimplement or configure by hand. platform-event-contracts has none of that shape: it contains only Avro schema definitions and their generated Java data-carrier classes (SpecificRecord POJOs) plus, as of Feature 14.5, a small test-support helper packaged as a test-jar. It has zero AutoConfiguration classes, injects no runtime behavior into a consuming service's Spring context, and could not leak infrastructure into business code even in principle - depending on it is equivalent in kind to depending on a generated-DTO/protobuf-stubs module, not to depending on platform-core.

A2. Ruling: this dependency pattern is compliant, with a stated scope

Direct (non-starter) dependency on platform-event-contracts - compile-scope where a service constructs or deserializes the canonical event types at runtime, test-scope (plus its test-jar classifier) where a service's contract tests assert against the canonical schema via AvroContractAssertions - is compliant with this ADR's Dependency Rule, not an exception to it. This carve-out is scoped to platform-event-contracts specifically (a pure schema/contract- definitions module, no AutoConfiguration, no runtime wiring). It does not extend to any other module under platform/ that is not itself a spring-boot-starter-* - platform-core, platform-autoconfigure, and similar internal modules remain fully subject to the unscoped Dependency Rule and MUST continue to be consumed only through a starter.

A3. Basis for the ruling - not a new pattern, an existing one confirmed

This is not a new allowance invented for Feature 14.5. Four services (usage-service, billing-service, notification-service, ticket-service) already depended on platform-event-contracts directly before this feature - two of them (billing-service, usage-service) at compile scope, i.e. in shipped production code, not merely in tests - and this had never been flagged as an ADR-018 violation through however many prior review passes those services went through. Feature 14.5 (phase 6, event-integration) extended the identical pattern, in test scope only, to 6 more services so every producing service's contract test could load the one real canonical schema instead of a hand-maintained local copy. Ratifying the existing, already-shipped pattern explicitly - rather than leaving it as one agent's unescalated reading of an absolute sentence - is what this amendment closes.

A4. What would make this a real violation

If platform-event-contracts ever gains an AutoConfiguration class, a Spring bean that performs I/O or business logic, or any other form of injected runtime behavior, it stops qualifying for this carve-out at that point and must be re-evaluated - either split into a schema-only module plus a proper starter, or re-escalated to tech-lead. This amendment covers the module as it exists today (schemas, generated data classes, test-support assertions only), not whatever it might become.