September 21, 2026 · 5 min read
Event Schema Validation Belongs in CI, Not in a Postmortem
Every tracking bug I've traced back far enough ends at a schema change that shipped without anyone checking it against what downstream systems expected.
Every tracking postmortem I've written in the last two years, traced back far enough, ends at the same root cause: an event's shape changed somewhere upstream and nothing caught it before it reached production. A renamed field, a type that changed from number to string, a nested object that got flattened during a refactor. None of these are exotic bugs. All of them are exactly the kind of thing a schema check in CI catches in seconds, and none of them were caught that way because no such check existed.
The frustrating part is that this is a solved problem in every other part of modern software engineering. API contracts get validated in CI constantly. Nobody ships a breaking API change without a test catching it first, in any team with basic engineering discipline. Event tracking gets treated as a second-class citizen in that discipline, even though a broken tracking event has real business cost — it's just a cost that shows up weeks later in a confused report instead of immediately in a failed build.
What this actually looks like in practice
# CI step: validate data layer output against committed JSON schema
npm run build:test-pages
npx ajv validate -s schemas/purchase-event.schema.json -d dist/datalayer-snapshot.json
# fails the build if the snapshot doesn't match the committed schemaA tracking bug caught in CI costs a failed build. The same bug caught three weeks later costs a reconciliation project and a client meeting explaining why the numbers were wrong.
How I've actually implemented this
- Committed JSON schemas for every major tracked event, versioned in the same repo as the frontend code that produces them.
- A CI step that renders key pages in a headless browser, captures the resulting data layer output, and validates it against the committed schema.
- A failing validation blocks the merge, same as any other failing test — no special exception carved out for tracking code.
- Schema changes require an explicit PR touching the schema file itself, which naturally surfaces the change for review instead of happening silently inside a broader refactor.
This took about a day to set up on a recent project and has already caught two breaking changes before they reached production. That's a day of setup against what would otherwise have been two more postmortems, and I don't think that math is close.