Migrating Off InventoryBase Without Stopping the Business

How I moved a property inventory agency's 14 years of InventoryBase data, 60,000+ inspections and 4 TB of photos, to its own platform while staff kept working.

A UK property inventory agency asked me to move 14 years of inspection history out of InventoryBase and into a platform it owns: more than 25,000 properties, over 60,000 inspections and more than 4 TB of reports and photos. The team used the system every day, so there was no weekend where everything could stop.

This post is about how that migration was planned and run. The case study covers the project as a whole. Here I focus on the parts that apply to anyone leaving a hosted inventory platform, or any SaaS product that holds years of operational records.

Why agencies leave a hosted platform

The agency had three reasons: the cost of keeping its whole history on a third-party platform, owning its records outright, and having a complete backup it controls. None of them was urgent on its own. Together they made the case, because every year of new inspections made the eventual move larger.

There was also a practical problem. Between InventoryBase and the team's Airtable base sat a sync service a freelance developer had started and never finished. It worked most days. When it did not, someone had to notice, find the failed job and run it again by hand. It kept its own copy of the data it passed through, but not in a form anyone could rely on as a backup.

Take over the live work before touching the history

The instinct on a migration is to start with the archive, because it is the big, visible job. I started with the sync instead.

The new Rails platform first took over everything the old service did: receiving changes from InventoryBase and Airtable, keeping the two in step in both directions, and writing back only the small set of fields the team was allowed to change from Airtable. Once that ran reliably, the old service could be switched off, and its database was imported into the new platform.

Doing it in this order meant the riskiest dependency was gone before the long import began. It also meant the new platform had been handling real, daily traffic for a while before it was trusted with the archive.

Every incoming change arrives as a signed webhook and is recorded before it is processed. If processing fails, the event goes to a dead-letter list where it can be inspected and replayed. That is the part the old service lacked: a failure became a retry, not a mystery.

Import one record at a time, and make it resumable

An inspection in InventoryBase is not one record. The import fetched each property with its contacts, meters and photos, and each inspection with its report, report details, contacts and attachments, across 14 inspection types.

It works through the list 50 records per page. For each record, it stores the raw response exactly as it arrived, then builds the tidied version the platform works with. Keeping the raw copy costs storage, but it means any question about migrated data can be answered from the original, long after InventoryBase is gone.

The import keeps its place. It only moves its bookmark forward once a record has fully imported, skips records it has already done, and leaves the bookmark alone if a record fails. That let me stop it, deploy a fix and start it again without losing work or copying anything twice. Records are matched on InventoryBase's own IDs, and a timestamp check stops an older imported value from overwriting a newer change that arrived by webhook in the meantime.

Respect the rate limits

InventoryBase limits how many requests an account can make. The import was paced to stay under that limit instead of racing it. When the API pushed back with a 429 or a temporary server error, it retried up to four times, waiting as long as the API asked or backing off on its own schedule, and logged every retry.

The slower historical backfills ran at 40 requests a minute, well inside the limit. Airtable needed the same treatment: it allows five requests a second, so the platform pauses between pages and marks a run as partial if Airtable's pagination expires, instead of pretending it finished.

A migration that trips a provider's rate limit is not just slow. It can lock out the people trying to work in the same account that morning.

Treat photos as their own migration

Photos were the biggest part of the job: more than 11 million files. They also fail in different ways from records. Some already existed in the agency's older storage and could be adopted by matching their filenames. Others had to be downloaded from InventoryBase. A few matched more than one candidate, and those were reported for a person to check, never picked automatically.

Photo work ran on its own queues, away from the webhook processing that keeps daily work in sync, so a large download never delayed a live change. I wrote about how the storage is split between a read-write bucket and a read-only legacy bucket in Hosting Is a Trust Problem.

Prove it before you delete anything

A finished import is not proof. Before anything could be deleted from InventoryBase, every property was checked against the source: its reports, report details, PDFs, meter readings and photos, each with its own status. Deletion only proceeds in checked batches, and so far a few thousand records have been removed.

The checks ran with read-only access and were paced so they would not compete with live traffic. The rule: nothing leaves the old platform until the new one can show it holds everything that record needs.

What I would tell anyone planning the same move

  • Move the live sync first. Once the daily work runs on your platform, the archive is a background job, not a cutover.
  • Keep the raw data from the source, next to your tidied version.
  • Make every import step resumable and safe to run twice.
  • Stay under the provider's rate limits by design, not by luck.
  • Treat photos and documents as a separate migration with their own failure modes.
  • Decide what "done" means per record before you start, and check against it before deleting anything.

The platform is now live and used daily, and I still maintain it. If you are planning to move off InventoryBase or a similar hosted platform, I am happy to talk through what your data looks like and where the risk sits.

Related writing