How to backfill content when adding new fields to Sanity schema?

6 replies
Last updated: Nov 29, 2025
Hello everyone, I am fairly new to Sanity and was wondering if there is a native solution or best practice for backfilling content when a new field is added to the schema or if one of the existing fields changes. For example, lets say I had a blog schema with content already created but I want to add a subtitle field, how would I backfill all the existing content to have the subtitle field?
AI Update

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:

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 create

This 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-run

Key Best Practices

The migration principles emphasize:

  1. Make it idempotent: Use setIfMissing instead of set so you can safely run the script multiple times without overwriting manually updated values
  2. Start simple: Begin with basic logic, test it, then add complexity incrementally
  3. Use dry-run mode: Always test first to preview changes before applying them
  4. 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:

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!

Show original thread
6 replies

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.

Was this answer helpful?