Salesforce governor limits are invisible until you hit them in production. Nimbus enforces them locally - the same limits, the same counts, the same errors - so you find out during development, not during a release.
Salesforce enforces resource limits per transaction: 100 SOQL queries, 150 DML statements, 12 MB of heap space. Exceed any of them and Salesforce throws a runtime exception that rolls back your entire transaction. No warning. No partial commit. Just a failure - often in production, after a data volume increase that your tests never exercised.
The problem is that limits don't show up in unit tests at low data volumes. A trigger that runs 3 SOQL queries per record is fine in a test with 10 records. In production with 200 records in a single batch, it blows past the limit on the first bulkified operation. Your 95% test coverage didn't catch it because your tests never pushed the boundaries.
Without local execution, you have no way to observe limit consumption during development. You deploy, you find out. With Nimbus, you find out locally.
// This trigger looks fine in a single-record test
trigger AccountTrigger on Account (before insert) {
for (Account acc : Trigger.new) {
// ❌ SOQL inside a loop - 1 query per record
List<Contact> contacts = [
SELECT Id FROM Contact WHERE AccountId = :acc.Id
];
acc.Contact_Count__c = contacts.size();
}
}
// With 10 records: 10 SOQL queries - passes
// With 101 records: 101 SOQL queries - System.LimitException
// nimbus test (strict mode): fails immediately, points at the loopNot every context needs the same level of enforcement. Local development benefits from fast feedback without blocking on every limit. CI should be strict - it's your quality gate. Nimbus gives you control through the nimbus.governor.mode setting.
Exceeding a limit fails the test immediately with a System.LimitException, exactly as Salesforce would. Use this in CI to enforce limits as a quality gate before every merge.
The test continues but a warning is printed. You see where the violation happened without the test failing. Good for local development - you're aware of limits without being blocked.
No limit tracking. Useful when writing tests for code that intentionally exceeds limits (to verify your exception handling), or when debugging unrelated issues and limits are noise.
The right configuration: warn locally so you stay informed without being blocked, and strict in CI so limit violations never reach main.
Use Nimbus's profile system to define this once, in your committed nimbus.properties file. Set NIMBUS_PROFILE=ci in your pipeline. No wrapper scripts, no per-developer configuration, no drift.
The off mode is also useful in a dedicated profile when testing exception-handling paths that expect a limit to be hit -NIMBUS_PROFILE=limits-off nimbus test ExceptionTest.
# nimbus.properties
# Local: warn on violations, stay unblocked
nimbus.governor.mode=warn
# CI: strict enforcement, fail on any violation
%ci.nimbus.governor.mode=strict
# Optionally tune the limits themselves
# (defaults match Salesforce's synchronous limits)
nimbus.governor.soql-queries=100
nimbus.governor.dml-statements=150
nimbus.governor.heap-size=12000000# Local development - violations warn, don't fail
nimbus test
# CI - violations fail the test
NIMBUS_PROFILE=ci nimbus test
# One-off: run with strict mode for a check
nimbus test --governor-mode strictNimbus tracks governor limit consumption per transaction and resets counters between tests. Each test method runs in full isolation - limits from one test don't bleed into the next.
| Property | Default | Description |
|---|---|---|
| nimbus.governor.soql-queries | 100 | SOQL queries per transaction |
| nimbus.governor.dml-statements | 150 | DML statements per transaction |
| nimbus.governor.heap-size | 12000000 | Heap size in bytes (12 MB) |
| Limits.getLimitQueries() | - | Read current limit in Apex - works the same as in a real org |
| Limits.getQueries() | - | Read current consumption - test your own governor-aware code |
Code that checks Limits.getQueries() and adjusts behavior accordingly can be tested locally too. Nimbus tracks consumption faithfully, so assertions against limit values behave exactly as they would in an org.
@isTest
static void testGovernorAwareBulkOperation() {
// Verify your service respects query limits
List<Account> accounts = new List<Account>();
for (Integer i = 0; i < 50; i++) {
accounts.add(new Account(Name = 'Test ' + i));
}
insert accounts;
Integer queriesBefore = Limits.getQueries();
BulkAccountService.processAll(accounts);
Integer queriesUsed = Limits.getQueries() - queriesBefore;
// Assert bulkification: should be 1 query for 50 records, not 50
System.assert(queriesUsed <= 3,
'Expected bulkified queries, got ' + queriesUsed);
}The classic governor violation. One query per record in Trigger.new blows the limit at 101 records.
// ❌ 1 query per record
for (Account acc : Trigger.new) {
List<Contact> c = [SELECT Id FROM Contact
WHERE AccountId = :acc.Id];
}
// ✓ 1 query total
Set<Id> ids = new Map<Id, Account>(Trigger.new).keySet();
Map<Id, List<Contact>> cMap = new Map<Id, List<Contact>>();
for (Contact c : [SELECT Id, AccountId FROM Contact
WHERE AccountId IN :ids]) {
if (!cMap.containsKey(c.AccountId))
cMap.put(c.AccountId, new List<Contact>());
cMap.get(c.AccountId).add(c);
}One DML per record is the most common bulkification mistake. Collect records and issue a single DML statement.
// ❌ 1 DML per record
for (Account acc : accounts) {
acc.Status__c = 'Active';
update acc;
}
// ✓ 1 DML total
for (Account acc : accounts) {
acc.Status__c = 'Active';
}
update accounts;Not in production. Governor limits enforced locally - the same limits, the same counts, the same exceptions - before the code ever reaches an org.