On the eve of a release, our project needed to build three targets in one go — the main app, a Today widget, and an Apple Watch companion app. A full build on a single machine took 38 minutes. We didn't have the budget to run a permanent CI cluster year-round, but release day genuinely couldn't afford that wait. We eventually landed on a middle ground: on release day, rent three cloud Mac mini nodes on the spot, spin them up into a "one-day build farm," fan the work out over an SSH matrix, then centralize signing and collect the artifacts once builds finish. The whole thing takes under 15 minutes to produce three upload-ready packages. This post documents the full setup.
When Multi-Node Setups Are Worth It
Not every project needs this. The rule of thumb is simple: if a single full build takes more than 20 minutes, or a release needs to produce packages for multiple targets or architectures at once, it's worth spinning up extra nodes temporarily. If you're just doing day-to-day coding and running unit tests, a single Mini Standard (24GB RAM) is plenty — keeping five nodes running year-round would just be wasted spend.
The core idea behind a multi-node farm is "rent by the day, tear down on demand": place the order the night before your release window, release the nodes right after shipping, and only pay for parallel compute on the day you actually need it.
Farm Topology and Node Roles
We picked roles based on each node's network paths and resources. Before assigning roles, check the console for the tiers currently offered at each node, and give the heavy-compile role to a node whose network path and resources fit the job.
| Node Role | Plan | Chip/RAM | Location | Daily Price | Responsibility |
|---|---|---|---|---|---|
| Primary build node | Mini Pro | M4 Pro / 64GB | US West | $59.3/day | Main App target, also handles signing/aggregation |
| Build node A | Mini Standard | M4 / 24GB | Tokyo | $40.1/day | Today widget target |
| Build node B | Mini Standard | M4 / 24GB | Seoul | $40.1/day | Watch App target |
All three together run $139.5/day. For comparison, going all-in on Mini Pro would be $177.9/day — the widget and Watch App build loads aren't heavy enough to justify it, so a Standard tier suffices there, leaving budget for the memory-hungry main app build.
Lesson learned: at first we put all five nodes in Tokyo. Once the primary build node and the signing node were merged into one machine, rsync transfers over the internal network were fast, but the US West node ends up handling the subsequent App Store Connect upload — so being closer to the upload endpoint mattered more than being closer to the developer. Pick the signing node's region based on proximity to the upload exit, not proximity to your team.
Dispatch Script and Execution
The coordinator is usually the primary build node itself. A simple Bash script dispatches targets to the subordinate nodes, runs them in parallel in the background, and waits at the end:
#!/bin/bash
set -e
NODES=("node-a.internal" "node-b.internal")
TARGETS=("WidgetExtension" "WatchApp")
for i in "${!NODES[@]}"; do
ssh "build@${NODES[$i]}" \
"cd ~/repo && xcodebuild -scheme ${TARGETS[$i]} \
-configuration Release -archivePath build/${TARGETS[$i]}.xcarchive \
archive CODE_SIGNING_ALLOWED=NO" &
done
xcodebuild -scheme MainApp -configuration Release \
-archivePath build/MainApp.xcarchive archive
wait
echo "all targets archived"
The key detail is that the subordinate nodes run with CODE_SIGNING_ALLOWED=NO, producing only unsigned .xcarchive bundles — certificates never need to be synced to those two machines. The primary build node holds the certificates itself, handles the signed build for MainApp, and waits on the artifacts from the other nodes.
Artifact Aggregation and Centralized Signing
Once the subordinate nodes finish building, push the .xcarchive bundles back to the primary node with rsync:
rsync -avz build@node-a.internal:~/repo/build/WidgetExtension.xcarchive ./build/
rsync -avz build@node-b.internal:~/repo/build/WatchApp.xcarchive ./build/
Once all three archives have landed, run xcodebuild -exportArchive on the primary node using a single set of provisioning profiles and certificates, then use fastlane's pilot upload to push all three packages to TestFlight in one pass. Signing happens on exactly one machine the whole way through, and private keys never touch the subordinate nodes — a detail that comes up repeatedly during security baseline reviews.
Before placing the order, it's worth running through a quick checklist:
- [ ] macOS and Xcode versions are identical across all five nodes (to avoid artifact architecture mismatches)
- [ ] The subordinate nodes' SSH public keys are already added to
authorized_keys - [ ] The signing node is located in a region close to the App Store Connect upload endpoint
- [ ] Each node still has free reinstall credits available — don't reinstall right before release
Common Pitfalls and Boundaries
Multi-node orchestration isn't always worth the overhead. If your project only has one target, or a full build already finishes in under 10 minutes, splitting across multiple nodes will add more waiting time from SSH scheduling and rsync transfer than it saves — just run it on one node. If one of your three targets is unusually memory-heavy (say, a target that runs ML model inference), give it a Mini Pro machine ahead of time instead of forcing it onto a Standard node.
Frequently asked questions
What project size justifies a multi-node build farm?
It pays off once a full build exceeds roughly twenty minutes, or when you must produce several targets (main app, widget, watch app) and architectures at once. Solo daily development is fine on a single Standard node.
How do you keep signing certificates consistent across nodes without leaking them?
Keep certificates and provisioning profiles on exactly one node, usually the US-West signing node. Other nodes only compile unsigned .app/.xcarchive output, then rsync it to the signing node for a single signing and upload pass, so private keys never touch multiple machines.
How do I decide which node takes the heavy-compile role?
Check the console for the tiers currently offered at each node, then weigh your team's network paths and where the artifacts get uploaded: give the heavy-compile role to a node with ample resources and low latency to your main contributors, and keep the signing-and-upload role on a node with generous outbound bandwidth.
Need a dedicated Mac mini for your builds?
Physical nodes in Singapore, Tokyo, Seoul, Hong Kong, and Silicon Valley, billed by the day — get your VNC/SSH credentials in under 10 minutes.
Rent a Mac mini now