Uncategorized

Understand & Fixing Salesforce System.LimitException: Too many query rows: 50001

Introduction to Salesforce Governor Limits

What are Governor Limits?

Salesforce is a multi-tenant environment, which means your code runs on a shared infrastructure. To ensure fair use of resources, Salesforce enforces limits known as governor limits. These rules help prevent any one user or org from monopolizing server resources.

Why Do They Exist in Salesforce?

Without these constraints, inefficient or malicious code could slow down or crash entire servers, affecting thousands of users. Governor limits protect system stability and ensure a consistent experience across all users.


Decoding the Error: “System.LimitException: Too many query rows: 50001”

Meaning of the Error

The error message System.LimitException: Too many query rows: 50001 means your Apex code has exceeded the allowed number of rows retrieved via SOQL in a single transaction.

When and Why It Occurs

This typically happens during:

  • Bulk data operations without optimized queries.
  • SOQL queries inside loops.
  • Large reports or data exports processed in Apex.

Salesforce Query Row Limits Explained

Per-Transaction Limits

One common misconception is that the 50,000 query row limit applies to each SOQL query individually. That’s not the case. This is a per-transaction limit, meaning all SOQL queries combined during a single Apex execution are counted together.

  • Synchronous Apex (Triggers, Controllers, etc.): 50,000 total rows
  • Asynchronous Apex (Batch, Queueable, Future): Up to 50 million rows (for Batch Apex)

Example:

List<Account> accounts = [SELECT Id FROM Account LIMIT 10000];
List<Contact> contacts = [SELECT Id FROM Contact LIMIT 45000];

The above would not cause a System.LimitException, since the total rows retrieved are 55,000, which would exceed the limit only in synchronous context. But if you’re in a batch job, it may be permissible depending on batch size.

Decoding the Error: “System.LimitException: Too many query rows: 50001”

When and Why It Occurs

This error doesn’t mean you’ve written one giant query pulling 50,001 records. Instead, all queries executed in a single transaction contribute to the limit. You might hit the limit if:

  • You execute multiple queries retrieving smaller sets that cumulatively exceed 50,000 rows.
  • Recursive triggers or helper methods make additional queries.

Limits by Context

Context matters—process builders, triggers, or visualforce controllers all follow different processing boundaries.


Code Scenarios That Trigger This Error

Loops with SOQL Inside

for(Account acc : accountList) {
    List<Contact> contacts = [SELECT Id FROM Contact WHERE AccountId = :acc.Id];
}

The above will execute one SOQL per loop = BAD PRACTICE.

Poorly Optimized Queries

Queries without proper filters or those returning entire tables also risk hitting the 50,000 limit.

How to Prevent the “Too Many Query Rows” Error

Bulkify Your Code

Always process records in bulk, not one at a time.

Use SOQL For Loops Properly

SOQL “for loops” are efficient because Salesforce handles query execution in chunks.

for(Contact con : [SELECT Id FROM Contact WHERE AccountId IN :accountIds]) {
    // process
}

Apply Selective Filters

Use WHERE clauses that match indexed fields. Avoid SELECT * unless needed.


Best Practices for SOQL Query Optimization

Indexing and Selective Queries

Use indexed fields like Id, Name, CreatedDate to filter records quickly.

LIMIT Clauses

Always restrict queries using LIMIT wherever feasible.

Using Relationship Queries

Use nested queries to reduce the number of separate queries.

SELECT Id, (SELECT Id FROM Contacts) FROM Account

Tools to Monitor Query Limits in Salesforce

Debug Logs

Monitor the number of rows retrieved by each SOQL query.

Developer Console

Use the Execution Overview panel to see resource usage.

Limits Class

System.debug('Query Rows used: ' + Limits.getQueryRows());

Handling Large Data Volumes in Apex

Batch Apex

Split large datasets into manageable chunks.

QueryLocator vs Database.Query

Use Database.getQueryLocator() in batch jobs for large data sets.

Use of Streaming and Platform Events

For near-real-time and scalable event handling.


Using Limits Class to Stay Within Boundaries

Limits.getQueryRows()

Returns the number of rows retrieved so far in the execution.

Limits.getLimitQueryRows()

Returns the maximum number of rows allowed in the execution.


Error Logging and Debugging Techniques

Set Checkpoints in Developer Console

Monitor state and execution points.

Logging with Custom Metadata

Create a logging framework that records Apex transactions and errors for easier debugging.


Case Study: Resolving a Real-Life 50001 Query Rows Error

Problem Outline

A developer used a SOQL query inside a loop processing 10,000 accounts, each with 6 contacts—resulting in 60,000 SOQL rows.

Step-by-Step Solution

  • Refactored the loop to use a bulk SOQL query.
  • Added filters and relationship queries.
  • Split operations using Batch Apex.

Performance Outcome

Error resolved, processing time reduced by 40%, and code was now governor limit safe.


Reference Materials and Salesforce Documentation


When to Refactor Apex Code

Code Reviews

Regular reviews help catch inefficient code.

Identifying Expensive Operations

Use profiling tools and logs to spot SOQL-intensive operations.


FAQs on Salesforce Query Limits

Q1. Can the 50,000 query row limit be increased?
No. It’s a hard limit in synchronous Apex. Use Batch Apex for higher volumes.

Q2. Does the limit apply to all types of orgs?
Yes. The limit is consistent across sandbox and production.

Q3. What’s the difference between getQueryRows() and getLimitQueryRows()?
getQueryRows() returns how many rows have been used; getLimitQueryRows() gives the maximum allowed.

Q4. Can I use OFFSET to skip rows?
Yes, but it doesn’t reduce the number of queried rows—it just skips output.

Q5. Will queries from other Apex classes count toward my transaction?
Yes, all SOQL queries in the same transaction are counted cumulatively.

Q6. How do I handle this error in a managed package?
Use best practices and batch processing to stay under limits and ensure scalable code.


Conclusion

Understanding the Salesforce System.LimitException: Too many query rows: 50001 error is crucial for writing scalable and efficient Apex code. By leveraging bulk processing, SOQL best practices, and Salesforce’s own tools, you can avoid this frustrating error and keep your apps running smoothly. Salesforce doesn’t allow you to bypass these limits—but with smart coding, you’ll never need to.