This is Anti-pattern—thoughts on programming and whatnot by Brandon Weiss.

Migrating to a New Mac for Programmers

Apple creates great experiences, but migrating to a new computer tends to not be one of them. There are several different ways of migrating, it’s not clear what the relative differences are between them, and when it’s taking a lot longer than you expect it’s not clear why. The seemingly never-ending migration hits programmers especially hard.

After running into this problem yet again recently, I did some research and experimented until I figured out what was wrong and how to fix it. Here’s what I learned.

Target Disk Mode

You may have gotten used to booting your old computer into Target Disk Mode and then having the new computer migrate the contents of the old hard drive over during setup. Don’t do that! I don’t exactly understand why, but it seems that Target Disk Mode can’t transfer at Thunderbolt speeds; it just degrades to regular USB transfer speed.

Migration Assistant

Instead of Target Disk Mode use Migration Assistant. Migration Assistant is an application you run on your old computer. It will restart into a special mode that is complementary to the setup mode your new computer boots into and will allow your new computer to transfer files from your old computer at Thunderbolt speeds.

Thunderbolt cable

Make sure you have a Thunderbolt cable. The situation with USB-C and Thunderbolt is confusing. The ports look identical and the cables almost look identical. The charging cable that comes with your Mac is not a Thunderbolt cable. You’ll know if you have a Thunderbolt cable because it will have a Thunderbolt symbol on at least one end of the cable.

The transfer can also be done over WiFi for convenience if you don’t have much data to migrate, so Migration Assistant will ask you to connect to your WiFi network, but it’s not very clear why it’s asking. It’s extremely easy to misunderstand what is happening and connect to your WiFi network even though you have no intention of migrating your data that way. If you then also mistakenly use a USB-C cable instead of a Thunderbolt cable, you can wind up starting the transfer thinking it’s using Thunderbolt when it’s actually using WiFi.

Thunderbolt ports

Not all USB-C ports on all MacBooks are Thunderbolt ports. I believe the 2016 and 2017 13-inch MacBook Pros without Touch Bar only support full-speed data transfer on the left two ports. You can’t use the right two ports. The 2016 and 2017 13-inch MacBook Pros with Touch Bar and the 2016 and 2017 15-inch MacBook Pros all have full-speed data transfer on all four ports. It’s really confusing. Thankfully, all the 2018 MacBook Pros with Touch Bar now support full-speed data transfer on all four ports.

Zip your code folder

The final hurdle is the files themselves. I noticed that the transfer speed would fluctuate all over the place. Sometimes it would spike up to Thunderbolt speeds but often it would slow to a crawl, causing the transfer to take hours longer than would be expected.

Eventually I realized that even though I only have about 400 GB of data to transfer, the reason why it takes so much longer than expected is because I’m a programmer.

Migration Assistant does a file-level copy—it copies each file one at a time. There’s overhead in starting to copy a file and finishing copying a file. That means it’s much faster to copy one big file than a lot of little files, even if in aggregate they’re the same size as the big file.

The work programmers do doesn’t take up a lot of space so it deceptively seems like the data should transfer quickly, but the package managers we use to install dependencies generally create a lot of files. I just looked at one project and the dependencies totaled ~120,000 files. Multiply that across 20 or 30 projects and that is what makes the transfer take so long.

The fix is to zip up the folder where you keep your code, delete the original folder, do the transfer, then unzip it afterwards.


Before I got around 5 MB/s when migrating. Sometimes it would spike up to 20 MB/s but only briefly. I don’t even know how long the transfer would have ultimately taken because I cut it off after 20 hours with only about two-thirds done.

I made another attempt after figuring all this out. This time the transfer started at 5 MB/s but slowly ramped up to 105 MB/s and held steady there for the rest of the migration.

It took 1 hour and 45 minutes. 🚀

Avatar
Brandon Weiss
Programmer at Domus
Get new posts in your inbox
I post a few times a year about programming and whatnot. No spam.