Skip to content

Event Schema Governance

Purpose: Formalize versioning, validation, and evolution process for domain & analytics events to ensure backward compatibility and reliable downstream consumption.

Related Story: US-401 (Event Schema Version Governance)

1. Principles

  • Backward Compatibility First: Additive changes preferred; removals or type changes are breaking.
  • Explicit Versioning: Each event schema carries an integer schemaVersion; increment on additive changes, block on breaking changes unless override approved.
  • Contract as Code: JSON Schemas stored in version control under docs/analytics/schemas/ and validated in CI.
  • Consumer Confidence: Deprecation windows and changelogs ensure downstream systems adapt gracefully.

2. Schema File Convention

<eventName>.v<version>.schema.json
Example: user_signed_up.v1.schema.json
Latest version symlink/alias optional (future). All schemas include: - $id: unique URI-like identifier - title: event name - type: object - required: mandatory fields - properties: field definitions - additionalProperties: false (prevent silent drift)

3. Versioning Rules

Change Type Allowed Without New Major? Action
Add optional field Yes Increment version (+1)
Add required field No (breaking) Reject or create new event variant
Remove field No (breaking) Reject; consider deprecation plan
Change field type No (breaking) Reject unless version bump + migration strategy documented
Add enum value Yes (if consumers tolerant) Increment version (+1)
Remove enum value No Reject

4. CI Validation Pipeline

Steps: 1. Detect modified/added schema files. 2. Run JSON Schema lint (structure, required fields present, disallow unknown keywords). 3. Compare old vs new schema for breaking changes using a diff tool. 4. If breaking change detected, block build unless ALLOW_BREAKING_EVENT_SCHEMA flag set (used only for emergencies). 5. Generate changelog entry into docs/analytics/event-schema-changelog.md. 6. Validate sample event payload fixtures under docs/analytics/fixtures/ against new schemas.

5. Compatibility Diff Logic (Pseudo)

for each changedEvent:
  old = loadPreviousVersionSchema(event)
  new = loadNewSchema(event)
  diff = compare(old, new)
  if diff.removedFields or diff.typeChanged or diff.requiredAdded:
      fail("Breaking change detected")
  else:
      pass and increment version

6. Deprecation Policy

Stage Description Duration
Active Latest + previous minor versions Indefinite
Deprecated Older versions marked; warnings logged if emitted 60 days
Sunset Emission blocked; CI fails if old version used After deprecation window

7. Changelog Format

Append to event-schema-changelog.md:

## <Date>
Event: <EventName>
Old Version: vX -> New Version: vY
Change: <Description>
Impact: <Consumer Impact Summary>
Migration Notes: <How to adapt>

8. Governance Roles

Role Responsibility
Publisher (Dev) Propose schema changes & fixtures
Data Engineer Review compatibility & analytics impact
Platform Architect Approve version increments, enforce policy
QA Validate fixtures & regression tests

9. Metrics & Monitoring

  • Count of version increments per sprint.
  • Number of blocked breaking attempts.
  • Consumer error rate (schema mismatch) < 0.1% events.
  • Time-to-adopt new version (median < 14 days).

10. Future Enhancements

  • Automated diff tooling output as PR comment.
  • Semantic versioning (major.minor.patch) if complexity grows.
  • Consumer subscription manifest referencing expected versions for proactive alerts.

11. Open Questions

  1. Support experimental event namespace (e.g., exp.) for rapid iteration?
  2. Provide tooling to auto-generate sample payload from schema? (fixtures sync)
  3. Enforce field description presence for documentation completeness?

Version: 1.0 (2025-11-22)