Use Nimbus for the 80% of tests that exercise business logic, SOQL, triggers, and class behavior — the ones you run dozens of times an hour. Use scratch orgs for the 20% that require platform features Nimbus doesn't replicate: complex sharing rules, approval processes, UI rendering. They're complements, not competitors.
What each one actually is
Scratch orgs
A scratch org is a temporary, configurable Salesforce org provisioned from your DevHub. Full platform fidelity — every feature works exactly as it does in production. Each developer typically gets their own, so there's no shared state. The catch: provisioning takes 30 seconds to several minutes, your source has to be pushed, and the org sits behind DevHub's daily and active limits (100 active / 200 per day for most editions).
Nimbus
Nimbus runs a complete Apex interpreter on your machine with an embedded PostgreSQL. SOQL executes as real SQL, triggers fire on DML, flows run from your .flow-meta.xml files, and each test runs in an isolated transaction. No org, no credentials, no internet. Tests typically finish in tens of milliseconds.
The numbers that matter
- Test run time, single test: scratch org ~5–15 seconds (deploy + execute + retrieve); Nimbus ~10–200 ms.
- Full suite (1000 tests): scratch org 8–20 minutes; Nimbus 30–90 seconds.
- First-time setup: scratch org 5–30 minutes (config, push, install); Nimbus < 1 minute (single binary).
- Operational cost: scratch org consumes DevHub limits and CI minutes; Nimbus runs on your laptop or CI runner — no external service.
- Credentials needed: scratch org requires JWT cert, connected app, DevHub access; Nimbus needs none.
Where scratch orgs win
- Full platform features. Complex sharing rules, OWD, role hierarchy, approval processes, async @future/@queueable/Batchable lifecycles, Visualforce/LWC rendering, real platform events end-to-end. Nimbus implements some of these, not all.
- Governor-limit fidelity. Heap size and CPU time are measured against Salesforce's own platform hardware. Nimbus can track structural limits (SOQL rows, DML statements) but resource-based limits aren't comparable across machines.
- Pre-deployment validation. The last gate before production — run on a real org to verify the deploy itself works.
- UI work. Anything that requires the org UI to render and respond.
Where Nimbus wins
- Inner-loop speed. Edit a class, save, see results before your hands leave the keyboard. The same loop in scratch orgs is a coffee break.
- Offline. Train, plane, coffee shop with no Wi-Fi — Nimbus runs.
- CI without an org. No JWT cert, no DevHub limits, no scratch org pool to exhaust. Standard JUnit XML and Cobertura XML plug into GitHub Actions, GitLab, SonarQube, Codecov.
- Agentic workflows. AI agents work in write-test-fix loops. The loop only works when tests run in seconds. Nimbus makes Apex viable for Claude Code, Cursor, and Copilot the same way Python and TypeScript already are.
- Per-developer cost. No DevHub limit consumed for every developer running tests all day.
How teams actually use them together
The pattern we see most often:
- Local development: Nimbus for every test run during active work. Watch mode re-runs affected tests on save.
- Pull-request CI: Nimbus runs the full suite as the merge gate. JUnit XML + Cobertura plug into the existing CI.
- Pre-deployment: a scratch org or sandbox runs the same tests as the final platform-fidelity check before promoting to production.
The DevHub-heavy "every PR provisions a scratch org" pattern goes away. Scratch orgs become a deployment-validation tool, not a development dependency.
Migration — what changes in practice
# Before: scratch-org loop
sf org create scratch -f config/project-scratch-def.json -d
sf project deploy start
sf apex run test --suite-names MySuite --result-format json --wait 10
# After: Nimbus loop
nimbus test "MySuite.*"Your sfdx-project.json, your classes, your triggers, your flows — Nimbus reads them in place. No copying, no parallel project, no separate test files. The same @isTest classes that run on the platform run locally.
Try it on your project
Install in one line, point Nimbus at the same repo your scratch org loop runs against, and run your existing tests. If the suite passes locally, you've just replaced the inner loop. If it doesn't, the failures tell you exactly which platform features still need a scratch org — and which ones don't.