# Migration Cutover Runbook

> Source: https://agilitycms.com/docs/developers/migration-cutover-runbook

This runbook covers the switch from your old site to the new one built on Agility: the content freeze, the final sync, publishing, redirects, the DNS change, cache and webhook checks, and how to roll back. It assumes the import itself is done and verified (phases 1 to 5 in [Migrating to Agility](/docs/developers/migrating-to-agility)). For the checks every new site needs before launch, also work through the [Website Deployment Checklist](/docs/developers/website-deployment-checklist).

Name one person as the **cutover lead**. They run this list, make the go or no-go call, and are the only one who can start a rollback.

## Two weeks before: rehearse

- **Run the whole import end to end at least once** into a non-production instance, and time it. The final sync on launch day should be a smaller re-run of the same script, not a new one.
- **If you will copy content between Agility instances with the CLI,** for example from a migration sandbox into production, run `agility sync` with `--preflight` first to see what it will do. Sync into a blank target: the sync can't adopt content that already exists on the target, synced items get new content IDs, and the sync never deletes or unpublishes anything on the target. See [AgilityCLI](/docs/developers/cli).
- **Soft-launch the new site on a temporary domain** with crawling turned off, and test it there.
- **Set up the production deployment** for your sitemap in Agility. A production deployment is what lets you test URL redirections from Agility. See [Sitemaps](/docs/developers/sitemaps).
- **Confirm preview works** on the new site, so editors can check changes before they publish after launch.
- **Write the rollback plan** (see below) and agree on what would trigger it.
- **Lower the TTL on the DNS records you will change** well ahead of launch, so the switch, and a rollback, spread quickly.

## A few days before: freeze

A content freeze stops content changing in two places at once.

- **Announce the freeze** to everyone who edits the old site: when it starts, when it ends, and who to contact for an urgent change.
- **Freeze the old system.** Allow only emergency edits, and log every one so it can be repeated in Agility.
- **Limit who can publish in Agility** until launch, so only the migration team changes what will go live.
- **Record the freeze point:** the time or sync token you will use to fetch only what changed (see the final sync below).

## Final sync

Fetch what changed in the old system since your last full import, and re-run your import for just those items:

| Source | How to get only the changes |
| --- | --- |
| WordPress | The REST API's `modified_after` parameter, for example `/wp-json/wp/v2/posts?modified_after=2026-10-01T00:00:00` |
| Contentful | The Sync API: pass the `nextSyncToken` saved from your last run |
| Other systems | A modified-date filter or export, or re-export the sections you know changed |

Because the import script looks up items by their source ID, a re-run updates existing items instead of duplicating them. Run batches one after another, and account for every failed item before you go on. Then repeat the verification checks: counts, linked content, assets, and a preview of the pages that changed.

## Publish

Imported content is in Staging. Publish it in batches:

- From code, a batch workflow call publishes up to 250 content items or pages at once. Every call is queued as a batch: poll it until it is processed, then check each item's `errorMessage`, because a processed batch can still contain failed items. See [Batches and the Batch API](/docs/javascript/management-sdk/batches).
- The Management API's item and page publish routes publish only the item or page. To include nested content, use the `publish-cascade` routes, or include the nested items in your batch.
- In the Agility Content Manager, publishing an item or page also publishes its nested linked content by default. See [Previewing, Publishing, and Content States](/docs/editors/preview-and-publishing).
- If you copy content between instances with the CLI, `--autoPublish` publishes only the items that are published on the source.

Publish shared content (authors, categories, shared components) before the pages that use it, then publish pages. Check a sample on the new site after each step.

## Redirects

- **Load the final redirect list** into Agility's URL Redirections list, by importing a file (`OriginURL`, `DestinationURL`, `HTTPCode`) or through the Management API (up to 250 redirects per call). Each origin URL can appear only once in an instance. See [URL Redirections](/docs/editors/url-redirections).
- **Use 301 for permanent moves.** Browsers cache 301 redirects heavily, so a wrong 301 is hard to take back. Use 302 for anything temporary.
- **Make sure the new site reads the final list.** Agility stores the redirects; your front end applies them. If your site loads the list at build time, rebuild after the final load. See [Implementing URL Redirects with Next.js](/docs/nextjs/implementing-url-redirects-with-next-js).
- **Test them** with the Test action in URL Redirections, which checks redirects 100 at a time and can export the results. See [Testing URL Redirections](/docs/editors/how-to-test-url-redirections). Test again with `curl -I` against the production domain once DNS has switched.

## Switch DNS

1. Confirm the new site is ready on its production host, with HTTPS working for the production domain.
2. Remove any temporary `noindex` or robots.txt block from the production site. Keep it on staging and preview hosts.
3. Change the DNS records to point at the new host.
4. Keep the old site running on a separate hostname, frozen, until the rollback window closes.
5. Watch traffic move over, then run the checks below against the production domain.

## Cache and webhook checks

There are two cache layers. Agility's CDN serves API responses and assets and invalidates cached content when you publish. Your own host's cache sits in front of your pages and is yours to clear. See [Content Delivery & CDN Architecture](/docs/developers/content-delivery-and-cdn-architecture).

- **Publish a test change** and confirm it appears on the production site in the time you expect.
- **Check your webhooks.** In **Settings > Webhooks**, open **History** for the webhook that refreshes your site and confirm recent deliveries succeeded. Point the webhook at the production URL itself: redirects count as failed deliveries. See [Webhooks](/docs/developers/webhooks).
- **Watch the API rate limit during full-site builds.** The Content Fetch API allows 10 uncached requests per second, and responses from Agility's CDN cache don't count. A cold build of a large site can exceed it, so limit build concurrency. See [Fetch API Status Codes and Caching](/docs/developers/fetch-api-status-codes-and-caching).
- **Check asset URLs.** Images and files should load from `cdn.aglty.io` (or your custom asset domain), not from the old site.
- **Check preview** with an unpublished change.

## Rollback plan

Decide before launch what would make you roll back, for example key pages failing, forms not submitting, or a large share of top URLs returning 404. Then:

1. **Point DNS back** at the old site, which is still running and frozen.
2. **Reopen editing** on the old system and tell editors.
3. **List anything created in Agility after launch,** so it can be carried back or redone at the next attempt.
4. **Fix and reschedule.** Your Agility content stays where it is. Redirects stored in Agility are applied by the new front end, so they don't affect the old site.

If the problem is one bad batch of content rather than the whole launch, you don't need a full rollback. Unpublish that batch with the same batch workflow call (operation `Unpublish`), or restore an earlier version of an item from its [version history](/docs/editors/versioning).

## Launch-day checklist

- [ ] Freeze is in place and announced; emergency edits are logged.
- [ ] Final sync finished with no unexplained failed items.
- [ ] Counts, linked content and assets verified after the final sync.
- [ ] Shared content published, then pages published; every batch checked for item errors.
- [ ] Final redirect list loaded, read by the new site, and tested.
- [ ] Production site has HTTPS, no temporary `noindex`, and a correct robots.txt and sitemap.xml.
- [ ] DNS switched; old site still reachable on its own hostname.
- [ ] A test publish appeared on the live site; webhook history shows successful deliveries.
- [ ] Preview works for editors.
- [ ] Analytics and third-party scripts load on the new site.
- [ ] Rollback triggers and owner confirmed with the team.

## After launch

- **First days:** watch your 404 logs and add redirects for any old URLs you missed. Check that publishing and webhooks keep working.
- **First weeks:** follow the monitoring steps in [Keep Your Search Rankings Through a Migration](/docs/developers/keep-search-rankings-through-a-migration).
- **End of the rollback window:** lift the freeze for good, archive a final export of the old system, then decommission it.

## Related

- [Migrating to Agility](/docs/developers/migrating-to-agility)
- [Website Deployment Checklist](/docs/developers/website-deployment-checklist)
- [Batches and the Batch API](/docs/javascript/management-sdk/batches)
- [URL Redirections](/docs/editors/url-redirections)
- [Webhooks](/docs/developers/webhooks)

---

## Related pages

- [Migrating to Agility](https://agilitycms.com/docs/developers/migrating-to-agility.md)
- [Migrate from WordPress to Agility](https://agilitycms.com/docs/developers/migrate-from-wordpress.md)
- [Migrate from Contentful to Agility](https://agilitycms.com/docs/developers/migrate-from-contentful.md)
- [Migrate from Sitecore to Agility](https://agilitycms.com/docs/developers/migrate-from-sitecore.md)
- [Keep Your Search Rankings Through a Migration](https://agilitycms.com/docs/developers/keep-search-rankings-through-a-migration.md)

Index of every docs page: https://agilitycms.com/docs/llms.txt
