---
title: "How Notion catches breaking schema changes before they reach production"
description: "Schema drift in typed API requests and queue tasks can cause incidents when contracts change without detecting whether old payloads remain valid. Notion's CI guardrail extracts schema types from the base branch and compares them with PR types using TypeScript's compiler API, checking whether the old type is assignable to the new one. The check auto-discovers registered API endpoints and queue task types, uses git archive for base files, and currently covers approximately 1,300 endpoints and 296 task types. Backward compatibility blocks changes that reject old data, while queue schemas also receive an advisory forward check for rollout ordering. The rollout began with warnings, then made backward checks blocking and added a GitHub label for intentional exceptions; type checking still cannot catch extra runtime validation or semantic behavior changes."
---

# How Notion catches breaking schema changes before they reach production

[Notion](https://yomu.fyi/company/notion) · Maya Lekhi · Apr 2, 2026

**Type:** Problem & solution

## Summary

Schema drift in typed API requests and queue tasks can cause incidents when contracts change without detecting whether old payloads remain valid. Notion's CI guardrail extracts schema types from the base branch and compares them with PR types using TypeScript's compiler API, checking whether the old type is assignable to the new one. The check auto-discovers registered API endpoints and queue task types, uses git archive for base files, and currently covers approximately 1,300 endpoints and 296 task types. Backward compatibility blocks changes that reject old data, while queue schemas also receive an advisory forward check for rollout ordering. The rollout began with warnings, then made backward checks blocking and added a GitHub label for intentional exceptions; type checking still cannot catch extra runtime validation or semantic behavior changes.

## Context

Schema drift can make existing API clients send payloads that new server code rejects with 400 errors. Queue tasks create an additional time-based compatibility problem because payloads may remain in Redis for extended periods, including scheduled events and reminders, while worker code changes after enqueueing.

## Approach / What changed

The CI guardrail extracts old schema types from the base branch, loads new types from the PR branch, and uses the TypeScript compiler API to check assignability. It automatically discovers API and queue schemas through allAPIs.ts and allTasks.ts, blocks backward-incompatible changes, and reports forward-compatibility risks for queue rollout ordering.

## Takeaways

- Backward compatibility is defined as OldRequestType being assignable to NewRequestType, meaning new code can handle every payload accepted by the old schema.
- Queue tasks require both directions of compatibility: backward checks are blocking, while forward checks advise deploying worker changes before enqueuers when new values may appear.
- The guardrail does not detect extra handler validation, type-compatible semantic changes, or runtime behavior changes; code review and tests remain necessary for those cases.

**Tags:** [API](https://yomu.fyi/topic/api), [CI/CD](https://yomu.fyi/topic/ci-cd), [Distributed Systems](https://yomu.fyi/topic/distributed-systems), [TypeScript](https://yomu.fyi/topic/typescript)

- Source: [Notion](https://www.notion.com/en-gb/blog/how-notion-catches-breaking-schema-changes)
- Source URL: https://www.notion.com/en-gb/blog/how-notion-catches-breaking-schema-changes
- Ingested by Yomu: 2026-09-09T05:19:34.894Z

[Read original post](https://www.notion.com/en-gb/blog/how-notion-catches-breaking-schema-changes)
