Skip to main content

Drift Detection

Drift detection catches accidental modifications to frozen schemas before they cause SwiftData crashes in production. It’s your first line of defense against schema-related bugs.

What is Schema Drift?

Schema drift occurs when you accidentally modify a schema version that’s already been frozen and shipped:
This change breaks SwiftData’s migration system because the internal hash no longer matches the shipped version.

Why Drift is Dangerous

SwiftData’s Internal Hashing

SwiftData generates internal hashes for each schema version. When a user opens your app:
  1. SwiftData reads the existing database
  2. Compares the stored schema hash with current schema hash
  3. If hashes match → no migration needed
  4. If hashes don’t match → trigger migration
The problem: If you modify a shipped schema, the hash changes, but SwiftData thinks it’s still v1.0.0. Result:

Fresh Installs Hide the Problem

Your simulator tests won’t catch this:

How Drift Detection Works

1. Checksum Generation

When you freeze a schema, FreezeRay generates a SHA256 checksum of the schema structure:
This checksum is stored in both:
  • The JSON fixture file
  • The Swift code (via macro expansion)

2. Drift Test Generation

FreezeRay scaffolds a drift test that runs on every test suite execution:

3. Checksum Comparison

The __freezeray_check_1_0_0() function:
  1. Computes current schema checksum
  2. Compares with frozen checksum
  3. Throws descriptive error if they don’t match

4. Clear Error Messages

When drift is detected, you get an actionable error:

What Triggers Drift Detection

Drift is detected when you change any part of a frozen schema:

Adding Models

Removing Models

Modifying Model Properties

Changing Property Types

Modifying Relationships

Changing Attributes

Running Drift Tests

Local Development

Drift tests run automatically with your test suite:

Continuous Integration

Add drift detection to your CI pipeline:
Any PR that modifies a frozen schema will fail CI.

Fixing Drift

Step 1: Identify the Drift

Run tests to see which schema drifted:

Step 2: Revert Changes

Undo modifications to the frozen schema:

Step 3: Create New Version

Create a new schema version with your changes:

Step 4: Add Migration

Define how to migrate from V1 → V2:

Step 5: Freeze New Version

Best Practices

Never use —force to overwrite fixtures. It defeats the purpose of drift detection.

Run Tests Before Every Commit

Fail Fast in CI

Configure CI to fail immediately on drift:

Use Type Aliases

Type aliases help prevent accidental modifications:

Edge Cases

Intentional Schema Updates (Dev Only)

During development, you might want to update an unfrozen schema:
No drift test exists yet, so modifications won’t trigger errors. Once you freeze it, the schema becomes immutable.

Force Overwriting (Last Resort)

If you absolutely must refreeze (e.g., fixtures corrupted):
Only use --force if you haven’t shipped v1.0.0 to production. Otherwise, you’ll break existing users.

Troubleshooting

False Positives

Symptom: Drift detected but schema hasn’t changed Causes:
  • File encoding changes (LF vs CRLF)
  • Whitespace differences
  • Comment changes
Fix: Drift detection only looks at semantic structure, not formatting. If you get false positives, file a bug report.

Drift Not Detected

Symptom: Modified frozen schema but tests pass Causes:
  • Drift test not added to test target
  • Test file not committed to git
  • Test target not building
Fix:

Next Steps

Schema Freezing

Learn how to freeze schemas and generate checksums

Migration Testing

Test migrations after detecting drift

CI Integration

Automate drift detection in your CI pipeline

First Freeze

Start using drift detection in your project