Decide in one pass: whether your remote Mac Ruby pipeline should lean on rubygems.org, a compliance-approved mirror, Git-sourced gems, or vendor/cache; how hard to push BUNDLE_JOBS; where BUNDLE_RETRY stops helping; and how to key CI caches so Gemfile.lock stays the contract. This page is an executable matrix—tables, env blocks, and a lockfile acceptance checklist. Browse the homepage, blog index, PHP Composer mirror matrix, Gradle/Maven cache matrix, and remote Mac build node guide—no login.
  • Cross-border RTT tax: hundreds of small HTTPS round trips to rubygems.org or CDN edges turn bundle install into a wall-clock hog even when bandwidth looks fine.
  • Git gem amplification: every git: or github: entry clones or fetches over the same long-haul path; shallow clones help until a ref needs history you did not fetch.
  • Parallelism collisions: raising BUNDLE_JOBS without watching disk queue depth on shared Apple Silicon hosts creates jitter for Xcode or CocoaPods jobs on the same runner.
  • Lockfile drift: developers resolve on laptops with different mirrors or Bundler minors; CI silently rewrites Gemfile.lock or fails checksum steps.

Scenarios & bottlenecks

Start by naming the dominant cost: metadata (dependency API calls), gem .gem downloads, or git object transfer. Remote Mac pools in 2026 often mix Ruby with iOS toolchains; a “fast” install that saturates NVMe queues still delays unrelated jobs. If your stack also pulls containers or Java artifacts, read Git and Docker pull acceleration and cross-border Git, npm, and Homebrew CI optimization so you do not tune Bundler in isolation.

Decision rule: choose the smallest change that removes the bottleneck. Prefer mirror + lock discipline before vendoring every gem; prefer vendoring before running a fragile multi-hop proxy chain nobody can reproduce locally.

Parallel install & connection-pool parameters

BUNDLE_JOBS controls how many gems Bundler resolves or fetches concurrently during bundle install. BUNDLE_RETRY sets how many times Bundler retries a failed network request per gem operation. Both apply to rubygems-style downloads; Git-sourced gems still depend on git behavior and authentication.

Parameter / command Starting point (shared remote Mac) When to change
export BUNDLE_JOBS=6 4–6 jobs when multiple tenants share one Mac; 8 only on dedicated hosts with spare IO. Drop if diskutil activity or latency spikes coincide with install; raise only after confirming headroom.
export BUNDLE_RETRY=5 3 on stable paths (Bundler default); 5 on flaky cross-border links. Beyond ~5, prefer mirror health checks and outer shell retries instead of infinite inner retries.
bundle install --jobs=6 --retry=5 Same numbers as env vars; useful in one-off scripts. Keep flags and env consistent across local and CI to avoid “works on my laptop.”
Outer shell retry threshold 3 attempts with sleeps 2s, 4s, 8s exponential backoff. Stop after third failure and page mirror or proxy owners—do not mask systemic outages.
GIT_HTTP_LOW_SPEED_LIMIT / GIT_HTTP_LOW_SPEED_TIME Example: 1000 bytes/s for 300 seconds on very slow links. Use alongside BUNDLE_RETRY for Git gems; tune per region after measuring clone stalls.

Copy-paste CI env block (bash):

export BUNDLE_JOBS=6
export BUNDLE_RETRY=5
export BUNDLE_PATH="$PWD/vendor/bundle"
export BUNDLE_WITHOUT="development:test"   # only if your pipeline truly skips those groups

for i in 1 2 3; do
  bundle install --frozen && break
  sleep $((2 ** i))
done

Swap --frozen for the frozen/deployment flag your Bundler version documents if you are not on Bundler 2.4+. Always pair frozen installs with a committed Gemfile.lock.

Cross-border mirrors & Git-source strategy

Mirrors accelerate rubygems.org by terminating TLS closer to the runner or by riding an approved corporate proxy. Git-source gems bypass rubygems mirrors entirely—you must authenticate and cache the right layer. Never paste production tokens into public logs; map CI secrets into Bundler or Git config in the job’s environment only.

Source pattern Typical setup Example command / env
Official rubygems.org Default when latency and policy allow; simplest mental model. No mirror; ensure outbound 443 is stable.
Regional / vendor mirror Compliance-approved host that mirrors rubygems indices and gems. bundle config set --global mirror.https://rubygems.org https://gems.example-mirror.example/
Enterprise gem proxy Artifactory, Nexus, or internal rubygems remote with audit trails. bundle config set --global mirror.https://rubygems.org https://nexus.example.com/repository/rubygems.org/
GitHub HTTPS gems github: shorthand or explicit git HTTPS URLs. export BUNDLE_GITHUB__COM=x-access-token:${GITHUB_TOKEN}
SSH Git remotes Private forks or servers that disallow HTTPS tokens. export GIT_SSH_COMMAND='ssh -i ~/.ssh/ci_ed25519 -o StrictHostKeyChecking=yes'

After changing mirrors, regenerate Gemfile.lock on a clean machine that uses the same mirror chain as CI. Mixed chains are the fastest way to get “checksum valid here, invalid there” failures.

Lockfile drift, vendor/cache, and CI cache keys

Treat Gemfile.lock as the binary contract between developers and CI. Caches should invalidate when that contract changes or when the Ruby interpreter changes. vendor/cache stores .gem files for offline or low-connectivity installs; BUNDLE_PATH (for example vendor/bundle) stores expanded installs and is larger and more platform-specific.

Artifact CI cache strategy Example cache key fragment
vendor/cache (.gem tarballs) Cache when you run bundle package in-repo or in an upstream job artifact. gems-${{ hashFiles('**/Gemfile.lock') }} (GitHub Actions style)
Bundler global cache (gem downloads) Point at fast APFS path via bundle config set cache_path or default under home; cache directory in CI. bundler-${{ runner.os }}-ruby${{ matrix.ruby }}-${{ hashFiles('**/Gemfile.lock') }}
vendor/bundle install tree Sometimes faster restore than reinstall; watch native extension and platform differences. Add ruby -v digest or .ruby-version hash to key.
Git gem objects Cache bundler cache plus optional bare mirror; key includes lock checksum and pinned ref. git-gems-${{ hashFiles('**/Gemfile.lock') }}

Gemfile.lock acceptance checklist (fail CI if any item breaks):

Check Command / signal Pass criteria
Lock present test -f Gemfile.lock File committed on default branch.
No unexpected drift bundle install --frozen (or equivalent) Exit 0; lock not rewritten.
Platform consistency Inspect PLATFORMS block in lock Includes CI platform (often ruby or x86_64-linux / arm64-darwin as required).
Bundler version alignment BUNDLED WITH section CI installs matching Bundler before install.
Git refs pinned Git entries in lock show SHA/tag No floating branch names in production locks.

FAQ

Should I set BUNDLE_DEPLOYMENT? On modern Bundler it forces deployment semantics similar to legacy --deployment: vendor path, frozen behavior, and no system-gem leakage. Use it when your images are ephemeral and you want CI to mirror production constraints.

Does bundle config belong in the repo? Prefer .bundle/config checked in only when every developer and agent must share identical paths; otherwise inject config in CI with documented env vars so laptops stay flexible.

How do I debug slow Git gems only? Run a throwaway job with bundle install --verbose, watch for repeated clone attempts, and confirm shallow fetch settings. Pair with the shell retry table above instead of raising BUNDLE_RETRY without bound.

Summary

Pick mirror versus direct rubygems based on compliance and measured RTT, not folklore. Cap BUNDLE_JOBS on shared remote Macs, raise BUNDLE_RETRY only into the single-digit range, and wrap installs with a three-attempt shell backoff. Commit Gemfile.lock, key caches on its hash plus Ruby version, and run frozen installs in CI. When you need Apple Silicon close to your mirrors—or a dedicated machine so Ruby installs stop fighting Xcode builds—renting a remote Mac from MacPull keeps queues short without buying hardware.

No-login next steps: homepage, purchase, help center, technical blog.

Buy speed and isolation the same way you buy compile capacity: pin the lockfile, tame parallel network work, and place CI where your gems actually land.

Remote Mac for Ruby & Bundler CI

Apple Silicon hosts with SSH access—run frozen bundle install jobs without shipping a Mac to every region. Open the homepage, purchase flow, help articles, or blog index anytime—no sign-in required.