---
# === IDENTITY ===
id: business/erp-integration/salesforce-governor-limits/2026
canonical_question: "What are the Salesforce Apex governor limits per transaction - SOQL, DML, CPU, heap, callouts?"
aliases:
  - "Salesforce Apex execution limits sync vs async"
  - "Salesforce SOQL query limit per transaction"
  - "Salesforce DML governor limits and CPU timeout"
  - "Salesforce callout and heap size limits"
entity_type: erp_integration
domain: business > erp-integration > salesforce-governor-limits
region: global
jurisdiction: global
temporal_scope: 2025-2026

# === SYSTEM PROFILE ===
systems:
  - name: "Salesforce Platform"
    vendor: "Salesforce"
    version: "API v63.0 (Spring '26)"
    edition: "Enterprise, Unlimited, Performance, Developer"
    deployment: cloud
    api_surface: "Apex Runtime (triggers, classes, Visualforce, Lightning)"

# === VERIFICATION ===
last_verified: 2026-03-02
confidence: 0.95
version: 1.0
first_published: 2026-03-02

# === TEMPORAL VALIDITY ===
temporal_validity:
  status: evolving
  last_breaking_change: "Spring '24 -- CPU time measurement methodology updated"
  next_review: 2026-08-29
  change_sensitivity: high

# === CONSTRAINTS ===
constraints:
  - "100 SOQL queries per synchronous transaction -- includes queries from triggers, process builders, and flows in the same execution context"
  - "10,000 ms CPU time limit for synchronous transactions -- exceeded = immediate transaction abort with System.LimitException"
  - "6 MB heap size for synchronous transactions -- large collections, JSON deserialization, and SOQL results all consume heap"
  - "Governor limits are per-transaction, not per-trigger -- cascading triggers share the same pool of limits"
  - "Certified managed packages get separate governor limit pools (additional 100 SOQL, 150 DML per package)"
  - "Future methods cannot call other future methods -- no chaining; use Queueable for chained async"

# === SKIP CONDITIONS ===
skip_this_unit_if:
  - condition: "User needs REST/SOAP/Bulk API rate limits (org-level, not per-transaction)"
    use_instead: "business/erp-integration/salesforce-api-capabilities/2026"
  - condition: "User needs Salesforce authentication flow guidance"
    use_instead: "business/erp-integration/salesforce-auth-flows/2026"
  - condition: "User needs NetSuite governance units"
    use_instead: "business/erp-integration/netsuite-governance-limits/2026"

# === AGENT HINTS ===
inputs_needed:
  - key: execution_context
    question: "Is the code running synchronously or asynchronously?"
    type: choice
    options:
      - "synchronous (triggers, Visualforce controllers, Lightning components)"
      - "asynchronous (@future, Batch Apex, Queueable, Scheduled)"
  - key: limit_type
    question: "Which governor limit are you concerned about?"
    type: choice
    options:
      - "SOQL queries (100 sync / 200 async)"
      - "DML statements (150)"
      - "CPU time (10s sync / 60s async)"
      - "heap size (6 MB sync / 12 MB async)"
      - "callouts (100 per transaction)"
      - "all limits -- general reference"
  - key: trigger_context
    question: "Is this code running inside a trigger?"
    type: choice
    options:
      - "yes -- trigger or trigger handler"
      - "no -- standalone Apex class"
      - "not sure"

# === DISTRIBUTION ===
canonical_source: "https://knowledgelib.io/business/erp-integration/salesforce-governor-limits/2026"
suggested_citation: "Source: knowledgelib.io -- AI Knowledge Library (verified 2026-03-02)"

# === RELATED UNITS ===
related_kos:
  depends_on: []
  related_to:
    - id: "business/erp-integration/salesforce-api-capabilities/2026"
      label: "Salesforce REST/SOAP/Bulk API rate limits and capabilities"
  solves: []
  alternative_to: []
  often_confused_with:
    - id: "business/erp-integration/salesforce-api-capabilities/2026"
      label: "Org-level API call limits (100K/24h) vs per-transaction governor limits"

# === SOURCES ===
sources:
  - id: src1
    title: "Execution Governors and Limits -- Apex Developer Guide"
    author: Salesforce
    url: https://developer.salesforce.com/docs/atlas.en-us.apexcode.meta/apexcode/apex_gov_limits.htm
    type: official_docs
    published: 2026-01-15
    reliability: authoritative
  - id: src2
    title: "Apex Governor Limits -- Salesforce Developer Limits and Allocations Quick Reference"
    author: Salesforce
    url: https://developer.salesforce.com/docs/atlas.en-us.salesforce_app_limits_cheatsheet.meta/salesforce_app_limits_cheatsheet/salesforce_app_limits_platform_apexgov.htm
    type: official_docs
    published: 2026-01-15
    reliability: authoritative
  - id: src3
    title: "API Request Limits and Allocations -- Salesforce Developer Limits Quick Reference"
    author: Salesforce
    url: https://developer.salesforce.com/docs/atlas.en-us.salesforce_app_limits_cheatsheet.meta/salesforce_app_limits_cheatsheet/salesforce_app_limits_platform_api.htm
    type: official_docs
    published: 2026-01-15
    reliability: authoritative
  - id: src4
    title: "Governor Limits in Salesforce (Updated 2024)"
    author: Onilab
    url: https://onilab.com/blog/governor-limits-salesforce
    type: technical_blog
    published: 2024-08-15
    reliability: moderate_high
  - id: src5
    title: "Salesforce Governor Limits -- Best Practices & Examples"
    author: Salesforce Ben
    url: https://www.salesforceben.com/what-are-salesforce-governor-limits-best-practices-examples/
    type: community_resource
    published: 2025-03-10
    reliability: moderate_high
  - id: src6
    title: "Salesforce API Rate Limits & How to Prevent Hitting Them"
    author: Coefficient
    url: https://coefficient.io/salesforce-api/salesforce-api-rate-limits
    type: technical_blog
    published: 2025-06-01
    reliability: moderate_high
  - id: src7
    title: "The Salesforce Developer's Guide to the Spring '26 Release"
    author: Salesforce
    url: https://developer.salesforce.com/blogs/2026/01/developers-guide-to-the-spring-26-release
    type: vendor_release_notes
    published: 2026-01-15
    reliability: high
---

# Salesforce Apex Governor Limits Per Transaction (2026)

## TL;DR

- **Bottom line**: Salesforce enforces per-transaction governor limits on every Apex execution context -- SOQL, DML, CPU, heap, and callouts all have hard caps that abort the transaction when exceeded.
- **Key limit**: 100 SOQL queries per synchronous transaction (200 async), shared across all triggers, flows, and process builders in the same execution context. [src1]
- **Watch out for**: Governor limits are per-transaction, not per-trigger -- cascading triggers, workflow rules, and process builders all consume from the same pool. A single DML operation can fire multiple triggers that collectively exhaust the 100-SOQL or 10,000 ms CPU budget. [src1]
- **Best for**: Reference card for any Apex developer, integration architect, or AI agent recommending Salesforce customization patterns.
- **Authentication**: N/A -- governor limits apply to all Apex execution regardless of authentication method.

## System Profile

This card covers Salesforce Apex governor limits as enforced by the Salesforce multitenant platform. These limits apply to all Apex code execution -- triggers, classes, Visualforce controllers, Lightning components, @future methods, Batch Apex, Queueable Apex, and Scheduled Apex. Limits apply uniformly across Enterprise, Unlimited, Performance, and Developer editions; edition differences affect org-level API call quotas (covered separately) but not per-transaction governor limits.

| Property | Value |
|---|---|
| **Vendor** | Salesforce |
| **System** | Salesforce Platform (Spring '26, API v63.0) |
| **API Surface** | Apex Runtime (triggers, classes, VF, Lightning, async Apex) |
| **Current API Version** | v63.0 (Spring '26) |
| **Editions Covered** | Enterprise, Unlimited, Performance, Developer |
| **Deployment** | Cloud |
| **API Docs URL** | [Execution Governors and Limits](https://developer.salesforce.com/docs/atlas.en-us.apexcode.meta/apexcode/apex_gov_limits.htm) |
| **Status** | GA |

## Rate Limits & Quotas

### Per-Transaction Governor Limits (Core)

<!-- Agents: this is the primary reference table. All numbers are per single Apex transaction. -->

| Limit Type | Synchronous | Asynchronous | Notes |
|---|---|---|---|
| **SOQL queries** | 100 | 200 | Includes queries from triggers, flows, process builders in same context |
| **Records retrieved by SOQL** | 50,000 | 50,000 | Use LIMIT clause or queryMore/Database.getQueryLocator for larger sets |
| **SOSL queries** | 20 | 20 | Each query returns max 2,000 records |
| **Records retrieved by SOSL** | 2,000 | 2,000 | Per single SOSL query |
| **DML statements** | 150 | 150 | Each insert/update/delete/undelete counts as 1, regardless of record count |
| **Records processed by DML** | 10,000 | 10,000 | Total across all DML statements in the transaction |
| **CPU time** | 10,000 ms | 60,000 ms | Exceeded = System.LimitException, transaction aborted |
| **Heap size** | 6 MB | 12 MB | Collections, deserialized JSON, SOQL results all consume heap |
| **HTTP callouts** | 100 | 100 | Includes REST, SOAP, and any external HTTP request |
| **Callout cumulative timeout** | 120 seconds | 120 seconds | Total across all callouts in the transaction |
| **Default callout timeout** | 10 seconds | 10 seconds | Configurable per request up to 120 seconds |
| **Future method calls (@future)** | 50 | 0 (batch/future) / 1 (queueable) | Cannot call @future from @future or batch |
| **Queueable jobs (System.enqueueJob)** | 50 | 1 | Queueable can chain to 1 more queueable |
| **sendEmail invocations** | 10 | 10 | Per Messaging.sendEmail call |
| **Push notification method calls** | 10 | 10 | Each call can send up to 2,000 notifications |
| **Maximum execution time** | 10 minutes | 10 minutes | Hard timeout regardless of CPU usage |
| **Trigger recursion depth** | 16 | 16 | Maximum nested trigger invocations |

[src1, src2, src4]

### Certified Managed Package Limits

Certified managed packages (AppExchange) receive their own separate governor limit pools in addition to the org's native code limits. This means managed package code does not consume the org's governor limit budget. [src1]

| Limit Type | Additional Allocation (per package) |
|---|---|
| SOQL queries | +100 (sync) / +100 (async, total 1,100 with 11 packages) |
| DML statements | +150 |
| Callouts | +100 |
| sendEmail | +10 |
| Database.getQueryLocator records | +10,000 |
| SOSL queries | +20 |

### Org-Level Async Apex Limits (24-hour rolling)

| Limit Type | Value | Notes |
|---|---|---|
| Asynchronous Apex executions | 250,000 or (user licenses x 200), whichever is greater | Shared across batch, queueable, scheduled, future |
| Concurrent batch jobs (queued + active) | 5 | Additional jobs queue until slot opens |
| Scheduled Apex classes | 100 (Developer: 5) | |
| Synchronous concurrent transactions (long-running) | 10 | Transactions running >5 seconds |
| Open query cursors per user | 50 | |
| Batch start method query cursors | 15 | |
| Batch execute/finish query cursors | 5 | |
| Batch Apex Database.QueryLocator records | 50,000,000 | Per batch job |
| Batch size (Database.executeBatch) | 200 records (default) | Configurable 1-2,000 |

[src1, src2]

### Org-Level API Request Limits (24-hour rolling)

These are NOT governor limits -- they are org-level quotas on API calls. Included here because agents frequently confuse them. [src3, src6]

| Edition | Base API Calls/24h | Per User License | Per Salesforce Platform License | Sandbox |
|---|---|---|---|---|
| Developer | 15,000 | -- | -- | -- |
| Enterprise | 100,000 | +1,000 | +1,000 | 5,000,000 |
| Unlimited | 100,000 | +5,000 | +5,000 | 5,000,000 |
| Performance | 100,000 | +5,000 | +5,000 | 5,000,000 |

Formula: `base + (user_licenses x per_license) + purchased_add_ons`

| API Limit | Value |
|---|---|
| Concurrent long-running requests (>20s) | 25 (production) / 5 (developer/trial) |
| Maximum API call duration | 10 minutes (600,000 ms) |
| Bulk API batch submissions/24h | 15,000 (shared Bulk 1.0 + 2.0) |
| Bulk API records per batch | 10,000 |
| Bulk API batch file size | 10 MB |

## Constraints
<!-- Agents: read this section before recommending any Apex or integration approach from this unit.
     These are hard constraints that must not be violated. -->

- **Limits are per-transaction, not per-trigger**: A single DML operation (e.g., `update accounts`) can fire before-update triggers, after-update triggers, workflow rules, process builders, and flows -- all sharing the same 100-SOQL, 150-DML, and 10,000 ms CPU pool. [src1]
- **No catching LimitException**: When a governor limit is exceeded, Salesforce throws `System.LimitException`, which cannot be caught by try-catch blocks. The entire transaction is rolled back. [src1]
- **@future cannot chain**: Future methods cannot call other future methods. Use Queueable Apex for async chaining (max depth: 1 queueable per async context). [src1]
- **Callout restrictions in triggers**: You cannot make HTTP callouts directly from a trigger. All callouts from trigger context must be delegated to @future or Queueable methods. [src1]
- **Mixed DML restrictions**: You cannot perform DML on setup objects (User, Group, etc.) and non-setup objects in the same transaction. Use @future or System.runAs() to separate contexts. [src1]
- **Heap is not just variables**: Heap includes SOQL query results held in memory, deserialized JSON/XML, and any object reference. A single query returning 50,000 rows of a large object can exhaust 6 MB heap instantly. [src4]

## Integration Pattern Decision Tree

```
START -- Developer hitting or worried about governor limits
|-- Which limit is being hit?
|   |-- SOQL queries (100 sync / 200 async)
|   |   |-- SOQL inside a loop?
|   |   |   |-- YES -> Bulkify: query ONCE before loop, use Map<Id, SObject> for lookups
|   |   |   +-- NO -> Check for cascading triggers consuming SOQL budget
|   |   +-- Need >50,000 rows?
|   |       |-- YES -> Use Database.getQueryLocator in Batch Apex (50M record limit)
|   |       +-- NO -> Add LIMIT clause, use selective filters (indexed fields)
|   |-- DML statements (150)
|   |   |-- DML inside a loop?
|   |   |   |-- YES -> Collect records in a List, single DML outside loop
|   |   |   +-- NO -> Check for process builders/flows adding DML statements
|   |   +-- Hitting 10,000 DML rows?
|   |       +-- Move to Batch Apex (processes records in chunks of 200)
|   |-- CPU time (10,000 ms sync)
|   |   |-- Complex logic in trigger?
|   |   |   |-- YES -> Move heavy processing to @future or Queueable
|   |   |   +-- NO -> Profile with Limits.getCpuTime() to find hotspot
|   |   +-- Need >10s processing?
|   |       +-- Use Batch Apex (60,000 ms per execute()) or Platform Events
|   |-- Heap size (6 MB sync)
|   |   |-- Large SOQL result set?
|   |   |   |-- YES -> Use FOR loop on SOQL (streaming), or reduce fields in SELECT
|   |   |   +-- NO -> Check for large String/JSON operations
|   |   +-- Need >6 MB?
|   |       +-- Move to async context (12 MB) or Batch Apex
|   +-- Callouts (100 per transaction)
|       |-- Callouts in a trigger?
|       |   |-- YES -> MUST use @future or Queueable (triggers block callouts)
|       |   +-- NO -> Batch external calls, use Composite API to reduce count
|       +-- Need >100 callouts?
|           +-- Use Batch Apex with Database.AllowsCallouts
+-- General approach
    |-- < 200 records -> Synchronous trigger/class (standard limits)
    |-- 200-10,000 records -> Queueable Apex (async limits, chainable)
    |-- > 10,000 records -> Batch Apex (50M record ceiling)
    +-- Real-time notifications -> Platform Events (separate transaction context)
```

## Quick Reference

| Operation | Sync Limit | Async Limit | How to Check Remaining |
|---|---|---|---|
| SOQL queries issued | 100 | 200 | `Limits.getQueries()` / `Limits.getLimitQueries()` |
| SOQL rows retrieved | 50,000 | 50,000 | `Limits.getQueryRows()` / `Limits.getLimitQueryRows()` |
| DML statements issued | 150 | 150 | `Limits.getDmlStatements()` / `Limits.getLimitDmlStatements()` |
| DML rows processed | 10,000 | 10,000 | `Limits.getDmlRows()` / `Limits.getLimitDmlRows()` |
| CPU time consumed | 10,000 ms | 60,000 ms | `Limits.getCpuTime()` / `Limits.getLimitCpuTime()` |
| Heap size used | 6 MB | 12 MB | `Limits.getHeapSize()` / `Limits.getLimitHeapSize()` |
| Callouts made | 100 | 100 | `Limits.getCallouts()` / `Limits.getLimitCallouts()` |
| Future calls made | 50 | 0-1 | `Limits.getFutureCalls()` / `Limits.getLimitFutureCalls()` |
| Queueable jobs added | 50 | 1 | `Limits.getQueueableJobs()` / `Limits.getLimitQueueableJobs()` |
| SOSL queries issued | 20 | 20 | `Limits.getSoslQueries()` / `Limits.getLimitSoslQueries()` |
| Email invocations | 10 | 10 | `Limits.getEmailInvocations()` / `Limits.getLimitEmailInvocations()` |

[src1, src2]

## Code Examples

### Apex: Checking Governor Limit Consumption at Runtime

```apex
// Input:  Running Apex code that needs to monitor limit consumption
// Output: Debug log with current consumption vs limits

public class GovernorLimitChecker {
    public static void logLimits(String context) {
        System.debug('=== Governor Limits [' + context + '] ===');
        System.debug('SOQL queries: ' + Limits.getQueries() + ' / ' + Limits.getLimitQueries());
        System.debug('SOQL rows: ' + Limits.getQueryRows() + ' / ' + Limits.getLimitQueryRows());
        System.debug('DML statements: ' + Limits.getDmlStatements() + ' / ' + Limits.getLimitDmlStatements());
        System.debug('DML rows: ' + Limits.getDmlRows() + ' / ' + Limits.getLimitDmlRows());
        System.debug('CPU time: ' + Limits.getCpuTime() + ' ms / ' + Limits.getLimitCpuTime() + ' ms');
        System.debug('Heap size: ' + Limits.getHeapSize() + ' / ' + Limits.getLimitHeapSize());
        System.debug('Callouts: ' + Limits.getCallouts() + ' / ' + Limits.getLimitCallouts());
        System.debug('Future calls: ' + Limits.getFutureCalls() + ' / ' + Limits.getLimitFutureCalls());
    }

    public static Boolean canAffordQuery(Integer needed) {
        return (Limits.getLimitQueries() - Limits.getQueries()) >= needed;
    }

    public static Boolean canAffordDml(Integer needed) {
        return (Limits.getLimitDmlStatements() - Limits.getDmlStatements()) >= needed;
    }
}
```

### Apex: Bulkified Trigger Pattern (Avoids SOQL/DML in Loops)

```apex
// Input:  Trigger on Account -- up to 200 records per batch
// Output: Related Contacts updated without hitting governor limits

trigger AccountTrigger on Account (after update) {
    Set<Id> accountIds = new Set<Id>();
    for (Account acc : Trigger.new) {
        Account oldAcc = Trigger.oldMap.get(acc.Id);
        if (acc.BillingCity != oldAcc.BillingCity) {
            accountIds.add(acc.Id);
        }
    }

    if (accountIds.isEmpty()) return;

    // 1 SOQL query regardless of batch size (uses 1 of 100)
    List<Contact> contactsToUpdate = [
        SELECT Id, MailingCity, AccountId
        FROM Contact
        WHERE AccountId IN :accountIds
    ];

    for (Contact c : contactsToUpdate) {
        c.MailingCity = Trigger.newMap.get(c.AccountId).BillingCity;
    }

    // 1 DML statement regardless of record count (uses 1 of 150)
    if (!contactsToUpdate.isEmpty()) {
        update contactsToUpdate;
    }
}
```

### Apex: Offloading Heavy Processing to Queueable

```apex
// Input:  Large data processing that exceeds sync CPU limits
// Output: Processed asynchronously with 60s CPU budget

public class HeavyProcessingJob implements Queueable, Database.AllowsCallouts {
    private List<Id> recordIds;

    public HeavyProcessingJob(List<Id> recordIds) {
        this.recordIds = recordIds;
    }

    public void execute(QueueableContext ctx) {
        // Async context: 200 SOQL, 60s CPU, 12 MB heap
        List<Account> accounts = [
            SELECT Id, Name, Industry, (SELECT Id, Email FROM Contacts)
            FROM Account
            WHERE Id IN :recordIds
        ];

        List<Account> toUpdate = new List<Account>();
        for (Account acc : accounts) {
            // ... complex logic ...
            toUpdate.add(acc);
        }

        if (!toUpdate.isEmpty()) {
            update toUpdate;
        }

        // Chain to next queueable if more work remains (max 1 chain in async)
        // System.enqueueJob(new HeavyProcessingJob(remainingIds));
    }
}

// Enqueue from trigger or controller:
// System.enqueueJob(new HeavyProcessingJob(accountIds));
```

### SOQL: Streaming Large Result Sets Without Heap Overflow

```apex
// Input:  Need to process >50,000 records without hitting heap limit
// Output: Records processed in streaming fashion

// BAD -- loads all 50K records into heap at once:
// List<Contact> contacts = [SELECT Id, Email FROM Contact LIMIT 50000];

// GOOD -- SOQL for loop streams records in batches of 200:
for (List<Contact> batch : [SELECT Id, Email FROM Contact WHERE Email != null]) {
    // 'batch' contains up to 200 records at a time
    // Previous batch is garbage-collected, keeping heap low
    for (Contact c : batch) {
        // Process individual record
    }
}
// Uses 1 SOQL query, processes up to 50,000 rows, minimal heap
```

## Anti-Patterns

### Wrong: SOQL Query Inside a Loop

```apex
// BAD -- consumes 1 SOQL per record. 200 records = 200 SOQL = LimitException
for (Account acc : Trigger.new) {
    List<Contact> contacts = [SELECT Id FROM Contact WHERE AccountId = :acc.Id];
    // Process contacts...
}
```

### Correct: Single Query with Collection Filter

```apex
// GOOD -- 1 SOQL regardless of batch size
Map<Id, List<Contact>> contactsByAccount = new Map<Id, List<Contact>>();
for (Contact c : [SELECT Id, AccountId FROM Contact WHERE AccountId IN :Trigger.newMap.keySet()]) {
    if (!contactsByAccount.containsKey(c.AccountId)) {
        contactsByAccount.put(c.AccountId, new List<Contact>());
    }
    contactsByAccount.get(c.AccountId).add(c);
}
for (Account acc : Trigger.new) {
    List<Contact> contacts = contactsByAccount.get(acc.Id);
    // Process contacts...
}
```

### Wrong: DML Inside a Loop

```apex
// BAD -- 200 records = 200 DML statements. Exceeds 150 DML limit.
for (Contact c : contactsToUpdate) {
    c.MailingCity = 'New York';
    update c; // 1 DML per iteration
}
```

### Correct: Collect and Batch DML

```apex
// GOOD -- 1 DML statement regardless of collection size
List<Contact> toUpdate = new List<Contact>();
for (Contact c : contactsToUpdate) {
    c.MailingCity = 'New York';
    toUpdate.add(c);
}
update toUpdate; // 1 DML, even for 10,000 records
```

### Wrong: Synchronous Callouts in Triggers

```apex
// BAD -- callouts are blocked in trigger context; throws CalloutException
trigger OrderTrigger on Order (after insert) {
    for (Order o : Trigger.new) {
        Http h = new Http();
        HttpRequest req = new HttpRequest();
        req.setEndpoint('https://erp.example.com/api/orders');
        req.setMethod('POST');
        HttpResponse res = h.send(req); // CalloutException!
    }
}
```

### Correct: Delegate Callouts to @future or Queueable

```apex
trigger OrderTrigger on Order (after insert) {
    Set<Id> orderIds = new Set<Id>();
    for (Order o : Trigger.new) {
        orderIds.add(o.Id);
    }
    OrderCalloutService.syncToErp(orderIds); // Delegates to @future
}

public class OrderCalloutService {
    @future(callout=true)
    public static void syncToErp(Set<Id> orderIds) {
        List<Order> orders = [SELECT Id, OrderNumber, TotalAmount FROM Order WHERE Id IN :orderIds];
        Http h = new Http();
        HttpRequest req = new HttpRequest();
        req.setEndpoint('https://erp.example.com/api/orders');
        req.setMethod('POST');
        req.setBody(JSON.serialize(orders));
        req.setTimeout(30000); // 30s timeout (max 120s cumulative)
        HttpResponse res = h.send(req);
    }
}
```

## Common Pitfalls

- **Trigger recursion consuming the SOQL pool**: A trigger on Account updates Contacts, which fires a Contact trigger that queries Accounts again. Each cascade consumes from the same 100-SOQL budget. Fix: `Use static Boolean flags to prevent re-entry, or implement a trigger framework with recursion guards.` [src1]
- **Process Builder + Flow + Trigger stacking**: A single record save can fire a before trigger, after trigger, process builder, workflow rule, and flow -- all in the same transaction. Each consumes governor limits from the same pool. Fix: `Audit all automations on the object using Setup > Object Manager > [Object] > Triggers/Flows/Process Builders. Consolidate to a single automation framework.` [src5]
- **Large JSON deserialization blowing heap**: Deserializing a 5 MB API response payload in synchronous context exhausts the 6 MB heap because the original String + the deserialized objects both occupy heap simultaneously. Fix: `Move to async context (12 MB heap) or parse streaming with JSON.createParser() instead of JSON.deserialize().` [src4]
- **SELECT * equivalent**: Using `SELECT Id, Name, ... (all fields)` on objects with many fields wastes SOQL rows and heap. Fix: `Select only the fields you need. Use FieldSet or dynamic SOQL for configurable field lists.` [src5]
- **Not using Database.Stateful in Batch**: Without Database.Stateful, instance variables reset between execute() calls. Developers add extra SOQL queries to re-fetch state, wasting the query budget. Fix: `Implement Database.Stateful to persist state across batch chunks. Be aware it increases heap usage.` [src1]
- **Assuming sandbox has same limits as production**: Developer Edition sandboxes have different org-level limits (15,000 API calls vs 100,000+, 5 concurrent long-running vs 25). Governor per-transaction limits are the same, but org-level capacity is lower. Fix: `Use a Full Sandbox or Partial Copy Sandbox for load testing.` [src6]

## Diagnostic Commands

```apex
// Check current governor limit consumption in Execute Anonymous
System.debug('SOQL: ' + Limits.getQueries() + '/' + Limits.getLimitQueries());
System.debug('SOQL Rows: ' + Limits.getQueryRows() + '/' + Limits.getLimitQueryRows());
System.debug('DML: ' + Limits.getDmlStatements() + '/' + Limits.getLimitDmlStatements());
System.debug('DML Rows: ' + Limits.getDmlRows() + '/' + Limits.getLimitDmlRows());
System.debug('CPU: ' + Limits.getCpuTime() + 'ms/' + Limits.getLimitCpuTime() + 'ms');
System.debug('Heap: ' + Limits.getHeapSize() + '/' + Limits.getLimitHeapSize());
System.debug('Callouts: ' + Limits.getCallouts() + '/' + Limits.getLimitCallouts());
System.debug('Future: ' + Limits.getFutureCalls() + '/' + Limits.getLimitFutureCalls());
System.debug('Queueable: ' + Limits.getQueueableJobs() + '/' + Limits.getLimitQueueableJobs());
```

```bash
# Check org-level API usage via REST API
curl -s -H "Authorization: Bearer $ACCESS_TOKEN" \
  "$INSTANCE_URL/services/data/v63.0/limits" | jq '.DailyApiRequests'

# Expected output:
# { "Max": 100000, "Remaining": 98500 }

# Check all org limits (async Apex, bulk API, etc.)
curl -s -H "Authorization: Bearer $ACCESS_TOKEN" \
  "$INSTANCE_URL/services/data/v63.0/limits" | jq '.'
```

```bash
# Query Apex execution logs for limit violations (via Tooling API)
curl -s -H "Authorization: Bearer $ACCESS_TOKEN" \
  "$INSTANCE_URL/services/data/v63.0/tooling/query/?q=SELECT+Id,Operation,Status,LogLength+FROM+ApexLog+WHERE+Status='Error'+ORDER+BY+SystemModstamp+DESC+LIMIT+10"
```

## Version History & Compatibility

| API Version | Release | Status | Governor Limit Changes | Notes |
|---|---|---|---|---|
| v63.0 | Spring '26 (Feb 2026) | Current | No governor limit changes | Named Query API GA |
| v62.0 | Winter '26 (Oct 2025) | Supported | No governor limit changes | -- |
| v61.0 | Summer '25 (Jun 2025) | Supported | No governor limit changes | -- |
| v60.0 | Spring '25 (Feb 2025) | Supported | No governor limit changes | -- |
| v59.0 | Winter '25 (Oct 2024) | Supported | No governor limit changes | -- |
| v58.0 | Spring '24 (Feb 2024) | Supported | CPU time measurement methodology updated | Last significant limit-related change |

[src1, src7]

### Deprecation Policy

Salesforce supports API versions for a minimum of 3 years after release. Versions are retired in groups -- check the Salesforce API version support matrix before pinning. Governor limits themselves rarely change between versions; when they do, it is typically an increase (more generous), not a decrease. [src1]

## When to Use / When Not to Use

| Use When | Don't Use When | Use Instead |
|---|---|---|
| Writing Apex triggers, classes, or controllers | Need org-level API call quotas per edition | Salesforce API request limits reference |
| Debugging LimitException errors in production | Need Bulk API batch size and file limits | Salesforce Bulk API 2.0 reference |
| Designing trigger architecture for high-volume objects | Need authentication flow guidance | Salesforce auth flows reference |
| Planning async processing strategy (batch vs queueable) | Need NetSuite or SAP transaction limits | System-specific governor limits card |
| Reviewing AppExchange package limit isolation | Need to understand Flow-specific limits (not Apex) | Salesforce Flow limits reference |

## Important Caveats

- Governor limits are per-transaction but the "transaction" includes ALL automation on the object -- triggers, process builders, flows, workflow rules, and validation rules all share the same limit pool. Audit everything before assuming you have budget. [src1]
- Certified managed packages from AppExchange get their own separate governor limit pools. However, unmanaged packages share the org's limits. Do not confuse the two. [src1]
- The Limits class methods (e.g., `Limits.getQueries()`) show consumption within the current transaction only. They reset to zero for each new transaction. [src2]
- Salesforce can impose additional "concurrent request" throttling during peak load independent of governor limits. This manifests as "Unable to process request" errors even when governor limits are not exceeded. [src3]
- These limits are current as of Spring '26 (API v63.0). Salesforce rarely decreases limits but may adjust measurement methodology (as with CPU time in Spring '24). Always verify against the official Apex Developer Guide for your API version. [src1]

## Related Units

- [Salesforce REST/SOAP/Bulk API Capabilities](/business/erp-integration/salesforce-api-capabilities/2026) -- org-level API rate limits, not per-transaction
