SOQL vs SOSL: When to Use Each (with 15 Real-World Query Examples)
Side-by-side syntax, 50K vs 2K row limits, when SOSL is faster, dynamic queries, encrypted-field gotchas, and 15 real queries you can paste into the dev console today.

TL;DR
- SOQL = "give me records from THIS object that match these conditions." One object per query, relationship traversal allowed, structured filtering.
- SOSL = "search this text across MANY objects at once." Multi-object full-text, fuzzy matching, optimized for the search bar use case.
- Limits per transaction: SOQL = 50,000 rows · SOSL = 2,000 rows. SOSL queries are also capped at 20 per transaction.
- Pick SOSL when: the user typed something into a search box. Pick SOQL otherwise.
If you've ever stared at the Developer Console wondering whether to write SELECT Id FROM Account WHERE Name LIKE '%Acme%' or FIND {Acme} IN Name FIELDS RETURNING Account, Contact, Lead, you're hitting the SOQL-vs-SOSL question. They look similar. They're not.
This guide gives you the 30-second decision rule, the syntax cheat sheet, and 15 real working examples for both — plus the limits, gotchas, and when each is genuinely faster.
The 30-second decision
Three tests; first "yes" wins.
- Does the user want to find records by typing something into a search box? → SOSL.
- Are you querying ONE object (with optional relationship traversal)? → SOQL.
- Are you querying MANY objects at once for the same text? → SOSL.
Most production code is SOQL. SOSL is for the search bar — and it's far better at it than SOQL would be.
SOQL — the workhorse
-- Basic
SELECT Id, Name, Industry FROM Account WHERE Industry = 'Software'
-- With relationship (parent → child)
SELECT Id, Name, (SELECT Id, FirstName FROM Contacts) FROM Account WHERE Name = 'Acme'
-- With relationship (child → parent)
SELECT Id, Name, Account.Industry FROM Contact WHERE LastName = 'Smith'
-- Aggregate
SELECT Industry, COUNT(Id) total FROM Account GROUP BY Industry HAVING COUNT(Id) > 5
Strengths:
- Up to 50,000 rows per transaction (SOSL caps at 2,000).
- Supports SQL-flavored aggregates: GROUP BY, COUNT, SUM, AVG, MAX, MIN.
- Relationship queries via dot notation or subquery — fetches related data in one call.
- Selective filtering on indexed fields uses the database index for sub-second performance.
Weaknesses:
- One root object per query. Can't say "find 'Acme' in any object."
LIKE '%foo%'is not full-text search; it's a slow database wildcard scan that can't use indexes.- No fuzzy / phonetic matching.
SmithandSmythare different to SOQL.
SOSL — the search-bar specialist
-- Basic
FIND {Acme} IN Name FIELDS RETURNING Account, Contact, Lead
-- With filter
FIND {acme*} IN ALL FIELDS
RETURNING Account(Id, Name), Contact(Id, Email WHERE CreatedDate > LAST_N_DAYS:30)
-- Phone-style
FIND {(555) 123-4567} IN Phone FIELDS RETURNING Contact, Lead, Account
Strengths:
- Searches many objects in one query. The
RETURNINGclause specifies which to bring back. - Full-text-style matching with wildcards (
*,?) and phrase search. - Uses Salesforce's search index (separate from the database index) — fast on big orgs.
- Phonetic and stemming for English-language searches (
runmatchesrunning).
Weaknesses:
- 2,000-row limit per query (and 20 SOSL queries per transaction).
- Can't do aggregates.
- The search index can be ~10–60 seconds behind real-time. Records inserted moments ago may not appear yet.
Side-by-side comparison
| Aspect | SOQL | SOSL |
|---|---|---|
| Scope | One object (relationships allowed) | Many objects |
| Row limit | 50,000 / transaction | 2,000 / transaction |
| Query limit | 100 (sync) / 200 (async) | 20 / transaction |
| Best for | Structured filters, reports, automation | Search bar, "find anything" |
| Index used | Database (per-field) | Search index (separate, async) |
| Aggregates | Yes (GROUP BY etc.) | No |
| Wildcard | LIKE '%text%' (slow, no index) | text* (fast, indexed) |
| Phonetic | No | Yes (English) |
| Real-time | Yes — query the live DB | Slight delay — search index lag |
15 real-world examples
SOQL examples
-- 1. All Accounts in the Software industry
SELECT Id, Name FROM Account WHERE Industry = 'Software'
-- 2. Top-10 largest Opportunities by Amount
SELECT Id, Name, Amount FROM Opportunity ORDER BY Amount DESC LIMIT 10
-- 3. Account with all its Contacts (subquery)
SELECT Id, Name, (SELECT Id, FirstName, LastName FROM Contacts)
FROM Account WHERE Name = 'Acme Corp'
-- 4. Contacts with their Account industry (parent traversal)
SELECT Id, FirstName, LastName, Account.Industry
FROM Contact WHERE Account.AnnualRevenue > 10000000
-- 5. Cases by status with count (aggregate)
SELECT Status, COUNT(Id) total
FROM Case WHERE CreatedDate = THIS_QUARTER
GROUP BY Status
-- 6. Opportunities closing in the next 30 days
SELECT Id, Name, CloseDate, Amount
FROM Opportunity
WHERE StageName != 'Closed Won' AND StageName != 'Closed Lost'
AND CloseDate <= NEXT_N_DAYS:30
-- 7. Find duplicate emails (HAVING)
SELECT Email, COUNT(Id) c
FROM Contact WHERE Email != null
GROUP BY Email HAVING COUNT(Id) > 1
-- 8. Tasks I own that are overdue
SELECT Id, Subject, ActivityDate
FROM Task
WHERE OwnerId = :UserInfo.getUserId() AND ActivityDate < TODAY AND IsClosed = false
-- 9. Self-relationship (parent Account → child Accounts)
SELECT Id, Name, (SELECT Id, Name FROM ChildAccounts) FROM Account WHERE ParentId = null
-- 10. Dynamic SOQL (Apex)
String soql = 'SELECT Id, Name FROM Account WHERE Industry = :industry';
List<Account> accts = Database.query(soql);
SOSL examples
-- 11. Find "Acme" anywhere in name fields, return Accounts/Contacts/Leads
FIND {Acme} IN Name FIELDS
RETURNING Account(Id, Name), Contact(Id, FirstName, LastName), Lead(Id, Company)
-- 12. Wildcard search starting with "soft"
FIND {soft*} IN ALL FIELDS
RETURNING Account(Id, Name), Opportunity(Id, Name)
-- 13. Phone number search
FIND {(415) 555-1234} IN Phone FIELDS
RETURNING Contact(Id, Name), Account(Id, Name), Lead(Id, Company)
-- 14. Multi-word phrase
FIND {"customer success"}
IN ALL FIELDS
RETURNING Account, Contact, Knowledge__kav
-- 15. Search with filter clause per returned object
FIND {urgent}
IN ALL FIELDS
RETURNING Case(Id, Subject WHERE Status != 'Closed' ORDER BY CreatedDate DESC LIMIT 50),
Knowledge__kav(Id, Title WHERE PublishStatus = 'Online')
When SOSL is genuinely faster
In benchmarks on a 50M-row org, SOSL beats SOQL LIKE '%foo%' by 10–100×. The reason: LIKE with a leading wildcard cannot use a database index. The DB scans the whole table. SOSL uses the search index, which is built specifically for this.
Rule: never write WHERE Field LIKE '%text%' against a large object. Either use SOSL or rebuild your query around a leading-edge match (WHERE Field LIKE 'text%', which CAN use the index).
Encrypted field gotcha
If you have Salesforce Shield Platform Encryption on a field, SOQL filtering on that field gets very slow. The platform must decrypt rows in memory before filtering. SOSL on encrypted fields is sometimes blocked entirely depending on the field type.
Workaround: don't filter on encrypted fields at all. Filter on a non-encrypted indexed field first to narrow the result set, then post-process.
Dynamic queries — when and how
Dynamic SOQL/SOSL lets you build the query at runtime in Apex. Use it when the user is choosing fields, objects, or filters at runtime (search builders, report customizers).
// Dynamic SOQL
public List<SObject> runQuery(String objName, String filter) {
if (!Schema.getGlobalDescribe().containsKey(objName)) {
throw new IllegalArgumentException('Unknown object');
}
String soql = 'SELECT Id FROM ' + String.escapeSingleQuotes(objName);
if (String.isNotBlank(filter)) {
soql += ' WHERE ' + filter; // ⚠ validate this!
}
return Database.query(soql);
}
Security caution: dynamic SOQL is the #1 source of SOQL injection bugs. Always:
- Use bind variables (
:value) instead of string concatenation when possible. String.escapeSingleQuotes()any user-provided text that has to be concatenated.- Validate object/field names against
Schema.getGlobalDescribe()before using them.
Common mistakes
LIKE '%text%'on a big table. Use SOSL. Always.- 20+
ORclauses on one query. Slows the optimizer dramatically. Refactor to multiple queries with collected results, or useIN :collection. - Querying inside a loop. This is a governor limits violation waiting to happen — see our cheat sheet.
- Forgetting the SOSL search lag. Inserted records take 10–60 seconds to be searchable. Don't assert SOSL hits immediately after insert in test classes without
Test.setFixedSearchResults. - Using SOSL for aggregates. SOSL doesn't support GROUP BY. If you need a count, use SOQL.
Frequently asked questions
Can I combine SOQL and SOSL in one transaction? Yes. Each has its own row + query budget. Mix freely.
Does SOSL work on external objects? Limited. The search index is built per object; external objects need to be specifically configured for global search.
How does this affect Agentforce? Agents call Actions that may issue queries. The same SOQL/SOSL rules apply. Bulk-safe Action design is critical.
Is LIKE ever fast?
Yes — when the wildcard is on the right side only (Name LIKE 'Acme%'). The database can use the index for prefix matches. The leading-wildcard form is the slow one.
What about Big Objects and Async SOQL?
Big Objects (__b) only support a subset of SOQL — no relationships, no aggregations, no GROUP BY. Async SOQL (deprecated for most cases) is being replaced by Data Cloud federation.
What to read next
- Apex, Governor Limits, External Object — the dictionary entries.
- Governor Limits Cheat Sheet 2026 — how SOQL/SOSL limits sit in the broader picture.
Drop the 15 examples into your dev console tonight. The decision rule sticks faster after you've run them.
Share this article
Sources
Related dictionary terms
Keep reading

Salesforce Governor Limits Explained: The 2026 Cheat Sheet (with Examples)
The canonical 2026 cheat sheet: SOQL/DML/CPU/heap limits, sync vs async, the most-hit limits in production, and 10 patterns to keep your org out of the red.

Salesforce Flow vs Apex in 2026: A Decision Matrix for Admins, Developers & Consultants
Flow vs Apex isn't a religious war anymore. Here's the 2026 decision matrix — capability gaps, governor limits, the 70/30 rule, and 12 worked scenarios with the right answer for each.
