How we migrated 900+ schedules for a dbt Cloud™ customer
This is the story of how we migrated 900+ schedules from dbt Cloud™ to Paradime. It's much easier and straightforward than you think.

Kaustav Mitra
·
7
min read

How we migrated 900+ schedules for a dbt Cloud™ customer
Recently, we did a huge and complex migration of 900+ dbt Cloud™ jobs to Paradime with many interconnected dependencies. We completed the entire migration in 10 days with plenty of time to ensure the migration went smoothly without glitches.
Given how extensive the migration was and the relatively less time it took, we decided to document how we went about migrating so that data teams in a similar situation would find this useful.
Many data teams shy away from migrating even though they feel locked in to dbt Cloud™ and not getting enough value from it.
However, the hardest part of moving 900+ dbt Cloud™ jobs onto Paradime wasn't the jobs.
It was the multiple other systems that needed those jobs and data to be present exactly where they were:
an external orchestration platform that triggered runs by job ID,
an internal data platform health dashboard, and
an internal agent system that polled both the dbt Cloud™ API, and custom CI checks wired into every dbt™ repo
Recreating 900+ schedules took only an afternoon using our dbt Cloud™ to Paradime importer. Re-pointing everything that depended on their IDs and endpoints - without a gap in a production warehouse that the whole organization depended on was the actual migration.
Here's how we sequenced it.
The baseline
The customer ran 900+ jobs across many dbt Cloud™ projects in a data mesh. The distribution was lopsided: one central project held 40% of the models, projects aligned to sales analytics, marketing analytics and finance held another 40%, and the remaining models were aligned to miscellaneous smaller teams and projects.
By environment it broke down to 700 production schedules, 150 development schedules, and 150 CI jobs - so whatever plan we used had to be equally correct for scheduled runs, dev iteration, and pull-request checks.
Why we never cut over everything at once
Two properties of the importer let us migrate one project at a time instead of betting everything on a single cutover.
First, a dbt Cloud™ project maps to a Paradime workspace one-to-one, so each project could be imported, validated, and enabled on its own schedule. Second - and this is the property that influenced the entire plan - we always import a job in Paradime as paused. The importer reads each job's config and recreates it as a Bolt schedule that does nothing until you enable it. That lets us import all schedules from the central project first, diff them against existing schedules in our platform and have none of them running. This ensured that nothing became live by accident.
The paused-by-default behavior, combined with leaving the dbt Cloud™ jobs disabled-but-not-deleted, meant rollback for any schedule was a two-toggle operation for the entire migration, right up until we chose to decommission.
Inventory first
Before connecting anything, we listed every environment, every environment variable - both the ones in the dbt Cloud™ UI and every env_var() call in the code, since Paradime stores Bolt-schedule variables and Code IDE variables separately - and every job with its cron, commands, and dependencies. That catalogue became the thing we validated imports against, workspace by workspace.
Then we picked four pilots, chosen to cover the mechanics we were least sure about rather than the jobs that ran most often: an S3 external-source load paired with a security-grants macro, a Python model, a job triggered by the external orchestrator, and a CI job. If those four came across cleanly, the patterns underneath the remaining 800+ schedules were the same patterns.
Setup: get one model to build before importing 900
We matched the warehouse connection to the customer's production config, bulk-loaded the environment variables into both the Bolt and Code IDE stores, and ran a single dbt debug in the Code IDE. That one command validates auth, profiles, and variables before any schedule exists to fail on them - it's the cheapest place in the whole process to catch a misconfigured connection. SSO went in alongside this with the customer's IT team.
The import checks that matter
Four config details that we ensured matched between dbt Cloud™ and Paradime pre- and post migration are:
Schedules run in UTC. Any cron that silently assumes a local timezone would run at the wrong time. So we re-checked everyone.
state:modified+CI commands lose their deferral target. Environment-level deferral isn't imported, so those jobs select nothing until you set the deferred schedule by hand.On-completion chains only resolve within a single import. A child job whose parent lived in a not-yet-imported project came in with no trigger. We wired those up once both sides existed.
Re-running the importer duplicates rather than reconciles. So a re-import meant deleting the prior set first.
Pilot: two days against real history
To kick things off, we selected four pilot jobs that we are going to run as pilots across the development and production warehouses. We enabled these four pilots - dev warehouse first, then production, and paused the identical jobs in dbt Cloud™ so nothing ran twice.
For two days we compared Bolt run history against the old dbt Cloud™ history: durations, row counts, failures. We switched the triggers from cron to the Paradime API, tested end to end before we turned things on in prod.
Cutover, one workspace at a time
With the patterns proven, we moved through workspaces in batches, always enabling upstream schedules before their downstream dependents so build order did not break. Each Bolt schedule went live as its dbt Cloud™ twin was disabled in the same motion, and the disabled jobs stayed in place for a week or two as rollback.
This is also where the dependent systems came across, which was the real work:
CI moved to Turbo CI, re-created per repo and validated on a throwaway PR before anything relied on it.
The API consumers - health dashboard, observability tooling, monitoring agent - were each repointed from the dbt Cloud™ API to Paradime's.
Alerting went to Bolt failure webhooks feeding the customer's existing channels, so on-call coverage never dropped.
One detail prevented a whole class of errors: dev-environment schedules got an explicit --target dev on each step. Without it, Bolt defaults to the workspace's production environment, and dev models quietly build into prod.
Hypercare runs on the calendar, not the pilot
A two-day pilot can't observe a weekly or monthly job - by definition it never fires in the window. So hypercare ran through a full schedule cycle: every daily, weekly, and monthly cron firing at least once under observation. Per workspace, per cycle, we confirmed schedules ran on time, CI fired on a test PR, alerts reached the right channel, and the Catalog reflected the latest production run. Rollback stayed a toggle the entire time.
Only after a clean cycle with nothing open did we delete the old jobs, revoke the token, and retire the dbt Cloud™ subscription.
What actually carried the migration
Three things that helped with a smooth migration are as follows:
The inventory. A complete map of environments, variables, and dependencies turned 900+ schedules into a checklist we could diff against instead of a number we had to trust.
Paused-by-default plus disabled-not-deleted. Because every job was imported switched off, the old jobs stayed recoverable, rollback was mechanical - which is what let us move through 900+ schedules without a maintenance-window mentality.
Treating the wiring as the migration. The schedules imported quickly. CI, external triggers, API consumers, and alerts were the part that took real work, and doing it workspace by workspace kept any mistake contained to only data models that were part of that workspace.
The migration was completed with zero downtime, no missed production runs and no full rollback. Not because the cutover was clever, but because at no point was more than one workspace exposed at a time.
Conclusion
Are you considering moving out of dbt Cloud™ but worried that it might be daunting? We have helped startups to enterprises with simple to complex projects move with zero downtime. Reach out to us at kaustav@paradimehq.com or sign-up for free at https://app.paradime.io.
With Paradime, customers reduce their costs, 10x the velocity of their development, and reduce technical debt by 83%.

