Best practices for backfilling content in Sanity when adding new fields to schema.
Great question! Backfilling content when adding new fields to your schema is a common scenario, and Sanity has a recommended approach for this using the CLI migration tool.
When you add a new field like subtitle to your blog schema, existing documents won't automatically have that field populated. Here's how to handle it:
Using Sanity's Migration Tool (Recommended)
The CLI migration tool is the recommended approach. It provides built-in abstractions, automatic batching to avoid rate limits, dry-run mode by default, and document validation against your schema.
Create a new migration:
npx sanity@latest migration createThis creates a migration file where you can use defineMigration to backfill your new field. For your subtitle example:
import {defineMigration, at, setIfMissing} from 'sanity/migrate'
export default defineMigration({
title: 'Add subtitle field to blog posts',
documentTypes: ['blog'], // Only target blog documents
migrate: {
document(doc, context) {
// Set a default value for subtitle if it doesn't exist
return at('subtitle', setIfMissing('Default subtitle'))
// Or derive it from another field:
// return at('subtitle', setIfMissing(doc.title?.substring(0, 50)))
}
}
})Run the migration:
# Dry run first (default) to see what would change
npx sanity migration run
# Then execute for real
npx sanity migration run --no-dry-runKey Best Practices
The migration principles emphasize:
- Make it idempotent: Use
setIfMissinginstead ofsetso you can safely run the script multiple times without overwriting manually updated values - Start simple: Begin with basic logic, test it, then add complexity incrementally
- Use dry-run mode: Always test first to preview changes before applying them
- Handle errors gracefully: Legacy content can be inconsistent, so plan for missing or corrupted data
Alternative Approaches
While the CLI migration tool is recommended, you can also:
- Use custom scripts with
sanity execfor more complex transformations with full programmatic control - Export to NDJSON format, modify the file, and re-import (less common for simple backfills)
For Your Specific Case
For adding a subtitle field to existing blog posts, you have several options:
- Set a default placeholder: Use
setIfMissing('Add subtitle here')so editors know to update it - Derive from existing content: Extract from the title or first paragraph:
setIfMissing(doc.title?.substring(0, 50)) - Leave it empty: If the field is optional in your schema, you might not need a migration at all—just let editors fill it in as they update posts
- Use AI: For more sophisticated backfilling, you could even use Agent Actions to generate subtitles based on the post content
The migration tool makes this straightforward and safe, with dry-run giving you confidence before touching production data!
Sanity – Build the way you think, not the way your CMS thinks
Sanity is the developer-first content operating system that gives you complete control. Schema-as-code, GROQ queries, and real-time APIs mean no more workarounds or waiting for deployments. Free to start, scale as you grow.