Data Model • Security & Sharing • Flows & Apex • LWC • Deployment • 2026

Salesforce Interview Questions

30 questions What each one tests, an answer frame, a spoken answer 35 min read

This page is for admins and developers facing a Salesforce round, from a first job to a senior platform role. Most Salesforce interviews start with the data model and relationships, move to profiles, permission sets, roles and sharing, then test flows, Apex triggers, governor limits and SOQL. Developer rounds add async Apex, Lightning Web Components, testing and deployment, and senior rounds end with a requirement to design end to end, a production story and a judgement call. Each question shows what the interviewer is really checking, the shape of a strong answer and a short answer you can say out loud. Try the code in a free Developer Edition org, then change the stories to your own.

Search all questions by round, difficulty and level, or save the ones you want to practise.

Data Model & SOQL 4 questions

Easy Technical round Fresher, Mid-level Practice question

1. What's the difference between a lookup and a master-detail relationship, and how do you choose between them?

What the interviewer is really testing:
Whether you know the real consequences of each relationship for ownership, sharing, deletion and roll-ups, not just that one field is required.
Answer frame:

Master-detail: parent required, child has no owner of its own and inherits sharing, deleting the parent deletes children, roll-up summaries on the parent.

Lookup: optional by default, child keeps its own owner and sharing, parent delete usually just clears the field or can be blocked.

Choice: master-detail when the child means nothing alone; lookup when it has its own life and owner.

Sample spoken answer:

"Both link a child record to a parent, but master-detail is a much tighter bond. With master-detail the parent field is always required, the child has no owner of its own, so it inherits sharing and security from the parent, and deleting the parent deletes the children. I also get roll-up summary fields on the parent, like a count of line items or a total amount. A lookup is looser. The field can be optional, each child keeps its own owner and sharing, and when the parent is deleted the lookup is usually just cleared, or I can block the delete. So I pick master-detail when the child makes no sense on its own, like invoice lines under an invoice. I pick a lookup when the child has its own life and owner, like a support case that points at a product."

Red flag to avoid:

Saying the only difference is that one field is required, and missing ownership, inherited sharing and cascade delete.

They may ask next:
  • Can you convert a lookup to master-detail on an object that already has data, and what has to be true first?
  • How would you show a total from child records when the relationship is only a lookup?
Say it in 60 seconds
Medium Technical round Fresher, Mid-level Practice question

2. How do you model a many-to-many relationship in Salesforce, say candidates applying to many job openings?

What the interviewer is really testing:
Whether you can design a junction object properly and understand how its two parents affect ownership, access and roll-ups.
Answer frame:

Junction object: a custom object with two master-detail fields, one to each side.

Primary parent: the first master-detail created drives the page look and the junction record's owner.

Access and roll-ups: users need access to both parents by default; roll-ups work on both sides.

Sample spoken answer:

"Salesforce has no direct many-to-many field, so I'd build a junction object. Here that's Job Application, with one master-detail to Candidate and another to Job Opening. Each application record is one pairing, and it's also the natural home for data that belongs to the pairing, like the date applied or the interview stage. The first master-detail I create becomes the primary one, which drives how the record page looks and where the junction record takes its owner from. By default a user needs at least read access to both the candidate and the job opening to see an application, which is usually what the business wants. I get roll-up summaries on both sides, so each job can show its number of applicants, and I'd add the related list to both parents so recruiters can work from either end."

Red flag to avoid:

Suggesting a multi-select picklist or a text field of Ids to link the records.

They may ask next:
  • What happens to the applications if a job opening is deleted?
  • When would you use two lookups on the junction object instead of two master-details?
Say it in 60 seconds
Easy Technical round Fresher, Mid-level Practice question

3. When would you use SOSL instead of SOQL? Give me an example of each.

What the interviewer is really testing:
Whether you know one is a precise query on known objects and the other a text search across many, and when each fits.
Answer frame:

SOQL: one object plus its relationships, exact filters, returns a list of records.

SOSL: text search across many objects through the search index, returns a list of lists.

Catches: SOSL may miss very fresh records and returns nothing in tests unless results are fixed.

Sample spoken answer:

"SOQL is for when I know which object I'm querying and exactly what I'm filtering on, like all open opportunities for one account. It returns a list of records of one object, and I can reach into parent and child records through relationships. SOSL is a text search over the search index. I use it when I know a word but not where it lives, like a user typing Acme into a custom search box, and I want matching accounts, contacts and leads in one call. It returns a list of lists, one per object, and it's much better than SOQL with leading wildcards for searching text across many fields. The trade-offs: SOSL results come from the index, so a record saved a moment ago might not show yet, and in tests SOSL returns nothing unless I set fixed search results. For exact filters and business logic, SOQL is the tool."

Code:
// SOQL: one object, exact filters
List<Opportunity> opps = [SELECT Id, Name FROM Opportunity
                          WHERE AccountId = :accId AND IsClosed = false];

// SOSL: one search term, several objects
List<List<SObject>> hits = [FIND 'Acme*' IN NAME FIELDS
    RETURNING Account(Id, Name), Contact(Id, Name), Lead(Id, Name)];
Red flag to avoid:

Saying SOSL is just SOQL for several objects, or using it for exact business filters.

They may ask next:
  • How do you test a method that uses SOSL?
  • Why is a SOQL filter with a leading wildcard slow on a big object?
Say it in 60 seconds
Medium Coding round Fresher, Mid-level Practice question

4. Write one query that returns accounts with their open opportunities, and one that lists contacts with their account owner's name.

What the interviewer is really testing:
Whether you can navigate relationships in SOQL both ways, using the right relationship names, instead of running several queries and stitching them together.
Answer frame:

Child to parent: dot notation on the relationship name, like Account.Owner.Name.

Parent to child: a subquery in the SELECT list using the plural child relationship name.

Custom: relationship names end in __r; child rows count toward the row limit.

Sample spoken answer:

"SOQL doesn't do joins the way SQL does; it follows relationships. Going up from child to parent, I use dot notation on the relationship name, so from Contact I can read Account.Name and even Account.Owner.Name, a few levels up. Going down from parent to children, I write a subquery inside the SELECT list using the child relationship name, which is usually the plural, so Opportunities on Account. For custom relationships the name ends in __r instead of __c, like Invoices__r. In the first query I get accounts in one industry with only their open opportunities nested inside each account, and in Apex I loop over acc.Opportunities. The second reads the owner's name straight through the account. Child rows count toward the query row limit, so on big accounts I'd keep the subquery filtered or move the work to a batch."

Code:
SELECT Id, Name,
       (SELECT Id, Name, StageName, Amount
        FROM Opportunities
        WHERE IsClosed = false)
FROM Account
WHERE Industry = 'Technology'

SELECT Id, LastName, Account.Name, Account.Owner.Name
FROM Contact
WHERE AccountId != null
Red flag to avoid:

Querying accounts, then querying opportunities for each account inside a loop.

They may ask next:
  • Where do you find the child relationship name for a custom lookup?
  • How would you find accounts that have no opportunities at all?
Say it in 60 seconds

Security & Sharing 4 questions

Easy Technical round Fresher, Mid-level Practice question

5. What's the difference between a profile, a permission set and a role? Which would you change to let a user see more records?

What the interviewer is really testing:
Whether you separate what a user can do with an object from which records they can see, the confusion behind most access bugs.
Answer frame:

Profile: exactly one per user; baseline object, field, app and system permissions, plus login hours and IP ranges.

Permission set: additive access on top, many per user, can be grouped; the modern way to grant most access.

Role: no object permissions at all; places the user in the hierarchy that decides record visibility.

Sample spoken answer:

"Profiles and permission sets control what a user can do: which objects they can create, read, edit or delete, which fields they see, which apps they get, plus system permissions. Every user has exactly one profile, and permission sets add access on top. A user can have many, and I can bundle them into permission set groups. The approach I follow is a lean profile with minimal access and everything else granted through permission sets, because it's far easier to maintain as people change jobs. A role is different. It doesn't grant object access at all. It places the user in the role hierarchy, which decides which records they can see, because people above you generally see what you own. So to let someone see more records, I'd look at their role and the sharing setup, not the profile. To let them edit a new field, I'd use a permission set."

Red flag to avoid:

Saying a role controls which objects or fields a user can edit.

They may ask next:
  • What can only be set on a profile and not on a permission set?
  • How would you give a temporary contractor extra access that must be removed later?
Say it in 60 seconds
Medium Technical round Fresher, Mid-level, Senior Practice question

6. Explain how record access works, starting from org-wide defaults. Can a sharing rule ever take access away?

What the interviewer is really testing:
Whether you understand the sharing model as layers that only open access up, which you need to design security and to debug visibility.
Answer frame:

Object access first: without object permission from a profile or permission set, nothing else matters.

Baseline: org-wide defaults set the most restrictive level for records you don't own.

Opening up: role hierarchy, sharing rules by owner or criteria, teams, manual and Apex managed sharing.

Narrowing: sharing rules never remove access; tighten the default or use restriction rules where supported.

Sample spoken answer:

"I think of it as layers. First the user needs object permission from their profile or a permission set, or nothing else matters. Then org-wide defaults set the baseline for records they don't own: private, public read only, public read/write, or controlled by parent for detail records. I set the default to the most restrictive level anyone needs, then open access up. The role hierarchy opens it to managers above the owner. Sharing rules open it to groups or roles, either by who owns the record or by criteria on the record, like all accounts in one region. After that there's manual sharing, account and opportunity teams, and Apex managed sharing for complex cases. So a sharing rule can only grant access, never remove it. To hide records from someone, I tighten the default and share back, or use restriction rules on the objects that support them."

Red flag to avoid:

Setting org-wide defaults to public read/write and trying to hide records with sharing rules.

They may ask next:
  • Why can't you set the org-wide default for a detail object separately from its master?
  • What's the difference between an owner-based and a criteria-based sharing rule?
Say it in 60 seconds
Hard Technical round Mid-level, Senior Practice question

7. Apex runs in system mode. What do with sharing, without sharing and inherited sharing change, and how do you enforce field-level security too?

What the interviewer is really testing:
Whether you know that sharing keywords only cover record access and how to enforce object and field permissions in code, a common security review failure.
Answer frame:

System mode: Apex ignores object and field permissions by default.

Sharing keywords: with sharing respects record access, without sharing ignores it, inherited sharing follows the caller.

Field security: WITH USER_MODE, AccessLevel.USER_MODE or Security.stripInaccessible, since sharing keywords don't check it.

Sample spoken answer:

"By default Apex runs in system mode, so it ignores the running user's object and field permissions, and depending on the sharing keyword it may ignore record sharing too. With sharing makes the class respect the user's record access, so queries only return records they can see. Without sharing ignores it, which I use deliberately, for example a service that must count every case in the org. Inherited sharing runs in whatever mode the caller is in, and falls back to with sharing when the class is the entry point, which makes it a safe default for utility classes. The part people miss is that with sharing is only about records. It doesn't check object or field permissions. For that I run queries WITH USER_MODE, pass AccessLevel.USER_MODE to Database methods, or use Security.stripInaccessible. For anything a Lightning component calls, I declare sharing explicitly and enforce user mode."

Code:
public with sharing class CaseService {
    @AuraEnabled(cacheable=true)
    public static List<Case> openCases(Id accountId) {
        return [SELECT Id, Subject, Status FROM Case
                WHERE AccountId = :accountId AND IsClosed = false
                WITH USER_MODE];
    }
}
Red flag to avoid:

Believing with sharing also hides fields the user has no permission to read.

They may ask next:
  • What sharing mode does a class with no keyword run in?
  • Which sharing mode does a trigger run in, and why does that matter for the handler class?
Say it in 60 seconds
Medium Situational round Fresher, Mid-level, Senior Practice question

8. A support rep can't see an account she needs, and her manager asks you to just give her View All Data so it's sorted today. What do you do?

What the interviewer is really testing:
Whether you protect least privilege under pressure while still unblocking the user quickly with a proper diagnosis.
Answer frame:

Say no, kindly: View All Data opens every record and rarely gets removed.

Diagnose: object permission, then the Sharing Hierarchy button on the record, owner and role.

Fix narrowly: sharing rule, account team or role fix; a manual share if it's urgent today.

Sample spoken answer:

"I wouldn't grant View All Data. It opens every record in the org, including things she shouldn't see, and it's the kind of permission that never gets taken back. But I also wouldn't leave her stuck, so I'd diagnose it quickly. First, does she have read access on Account at all through her profile or permission sets? Then I'd open the record and use the Sharing Hierarchy button to see who has access and why. Usually the account is owned by someone outside her branch of the role hierarchy and no sharing rule covers her team. The right fix matches the business rule: a criteria-based sharing rule for her team, an account team membership, or correcting her role. If it's urgent, a manual share on that one account solves today while the proper rule is agreed. Then I'd tell the manager what we changed and why."

Red flag to avoid:

Granting View All Data or Modify All Data to make the ticket go away.

They may ask next:
  • What if it turns out her whole team is missing access to a set of accounts?
  • How would you check access for a user without logging in as them?
Say it in 60 seconds

Automation 5 questions

Easy Technical round Fresher, Mid-level Practice question

9. Write a validation rule that stops users saving an open opportunity with a close date in the past. How would a data load bypass it?

What the interviewer is really testing:
Whether you can write a correct formula, know that true means blocked, and plan for data loads without deleting rules.
Answer frame:

Logic: the formula describes the bad case; true blocks the save and shows the message.

Scope: leave closed deals alone; put the error on the field with a message that says how to fix it.

Bypass: a custom permission in the formula, granted by permission set to the load user only.

Sample spoken answer:

"A validation rule formula describes the bad case: if it evaluates to true, the save is blocked and the user sees my message. So here I'd write AND, NOT IsClosed, and CloseDate less than TODAY. Closed deals are left alone, since their close date is naturally in the past. I'd show the error on the Close Date field so it appears right where the user fixes it, with a message that says what to do, like move the close date to today or later, or close the deal. Validation rules run on every save, whether it comes from the UI, the API, Apex or a flow, so a big data load would trip it too. For that I add a custom permission, say Bypass Validation, into the formula with NOT, and give it through a permission set to the integration user only for the load."

Code:
AND(
  NOT(IsClosed),
  CloseDate < TODAY(),
  NOT($Permission.Bypass_Validation)
)
Red flag to avoid:

Writing the formula for the good case, so every valid record is blocked, or deactivating the rule for every data load.

They may ask next:
  • How would you stop it blocking users who edit an old record but don't touch the close date?
  • What's the difference between ISBLANK and ISNULL in a formula?
Say it in 60 seconds
Easy Technical round Fresher, Mid-level, Senior Practice question

10. When would you build a record-triggered flow, and when would you write an Apex trigger instead?

What the interviewer is really testing:
Whether you choose tools on maintainability, complexity and volume rather than habit, and think about what already runs on the object.
Answer frame:

Flow first: field updates, related records, notifications and simple decisions that admins can maintain.

Apex when: heavy logic, large collections, complex error handling, callouts with retries, big data volumes.

Context: follow the object's existing pattern; mixed automation on one object is hard to debug.

Sample spoken answer:

"My default is to start with a flow, because admins can read and maintain it and it's quick to change. A record-triggered flow handles field updates, creating a related record, sending notifications and simple decisions really well. I move to Apex when the logic gets heavy: lots of nested conditions, working across big collections with maps, complex error handling, callouts that need retries, or very large data volumes where I need tight control over queries and CPU time. Apex also wins when the logic needs proper unit tests and has to be reused from several places. The other thing I weigh is what already exists. If an object has a mature trigger framework, I'll usually add to it rather than scatter logic across a trigger and three flows, because mixed automation on one object is where most debugging pain comes from. For anything new, I use Flow, not workflow rules or Process Builder."

Red flag to avoid:

Saying code is always better, or that flows have no limits, since flows share the same governor limits as Apex.

They may ask next:
  • What's one thing an Apex trigger can do that a record-triggered flow can't do well?
  • How would you move an old Process Builder to Flow without changing behaviour?
Say it in 60 seconds
Medium Technical round Fresher, Mid-level Practice question

11. What's the difference between a before-save and an after-save record-triggered flow, and how does that map to before and after triggers?

What the interviewer is really testing:
Whether you know which stage to use for same-record updates versus related records, which decides both performance and correctness.
Answer frame:

Before-save: changes the triggering record with no extra DML; fast, but can only update that record.

After-save: has the Id and system fields; creates or updates related records, sends emails.

Triggers: before triggers set fields on Trigger.new; in after triggers Trigger.new is read-only.

Sample spoken answer:

"A before-save flow, which Flow Builder calls fast field updates, runs before the record is written, so any change I make to the triggering record just goes in with the save. There's no extra DML, which makes it very fast, but it can only update that same record. An after-save flow runs once the record is saved, so it has the record Id and system fields, and it can create or update related records or send emails. It costs more, because each change to another record is more DML. Triggers follow the same idea. In a before trigger I set fields directly on Trigger.new with no DML statement. In an after trigger the record has an Id, which I need to create child records, but Trigger.new is read-only, so changing the same record means a separate update, which also fires the trigger again. So same-record fields go before, related records go after."

Red flag to avoid:

Doing same-record field updates in an after trigger with an extra update call.

They may ask next:
  • Why is updating the triggering record in an after-save flow a bad idea?
  • When would you use the asynchronous path of an after-save flow?
Say it in 60 seconds
Hard Technical round Mid-level, Senior Practice question

12. Walk me through what happens, in order, when a user saves a record that has validation rules, flows and triggers on it.

What the interviewer is really testing:
Whether you can reason about where a value was changed or why a rule fired, which is most of real Salesforce debugging.
Answer frame:

Before the save: system validation, before-save flows, before triggers, then custom validation and duplicate rules.

After the save: after triggers, then assignment, auto-response and workflow rules, then after-save flows.

Parent and commit: roll-ups update the parent, sharing is recalculated, then commit.

Post-commit: emails and async jobs only start after the commit.

Sample spoken answer:

"When a user saves, Salesforce loads the record and runs system validation, like required fields and field formats. Then before-save flows run, then before triggers. After that it runs system validation again along with my custom validation rules, then duplicate rules. Then the record is saved to the database, but not committed. After triggers run next, then assignment, auto-response and any old workflow rules, and then after-save flows. If there are roll-up summary fields, the parent record is updated, which can fire the parent's own automation. Criteria-based sharing is evaluated, and only then does everything commit. Post-commit work comes last: emails are sent and async jobs like queueables start. So custom validation rules see values changed by before triggers, and a failure anywhere before commit rolls the whole thing back. Also, with several triggers on one object, their order isn't guaranteed, which is why I keep one trigger per object."

Red flag to avoid:

Putting custom validation rules before the before triggers, or thinking emails go out before the transaction commits.

They may ask next:
  • Why does a validation rule sometimes fire on a value the user never typed?
  • If an old workflow field update changes the record, what runs again?
Say it in 60 seconds
Hard Situational round Senior Practice question

13. An admin wants to add a record-triggered flow on Opportunity, which already has a large Apex trigger framework. What do you advise?

What the interviewer is really testing:
Whether you can weigh order of execution, recursion and ownership on a shared object, and guide a colleague without simply blocking them.
Answer frame:

Ask first: what the flow does decides the advice.

Same-record fields: a before-save flow is cheap and runs before the before triggers.

Related or dependent logic: after-save flows run after the after triggers and can re-fire them; consider the Apex handler.

Guardrails: document it, share the bypass switch, test with a bulk load.

Sample spoken answer:

"I'd start by asking what the flow needs to do, because that changes the advice. If it's a simple field update on the same record, a before-save flow is cheap and runs before the before triggers, so the Apex will see the new value. If it updates related records or depends on values the trigger sets, I'd be more careful. After-save flows run after the after triggers, and a flow that updates the opportunity again re-fires the whole trigger framework, which costs CPU time and can cause loops. In that case I'd suggest adding the logic to the Apex handler, or exposing it as an invocable action the team owns. Whatever we pick, I'd make sure it's on the object's automation map, respects the same bypass switch, and is tested in a sandbox with a bulk load, not just one record in the UI. I'd frame it as protecting the admin's change, not blocking it."

Red flag to avoid:

Either banning flows on the object outright or letting the flow go in with no thought about order and recursion.

They may ask next:
  • How would you control the order of several record-triggered flows on the same object?
  • What would you look for in a debug log if the flow and trigger disagreed on a field value?
Say it in 60 seconds

Apex & Limits 4 questions

Easy Technical round Fresher, Mid-level Practice question

14. What are governor limits, why do they exist, and which ones do you run into most often?

What the interviewer is really testing:
Whether you understand the multi-tenant reason behind limits and know the common numbers well enough to design code that stays under them.
Answer frame:

Why: shared servers; each transaction gets hard limits so one tenant can't hurt the rest.

Common ones: 100 SOQL queries and 150 DML statements per sync transaction, 50,000 query rows, 10,000 DML rows, CPU time.

Cause and check: queries or DML inside loops; watch with the Limits class and debug logs.

Sample spoken answer:

"Salesforce is multi-tenant: many customers share the same servers, so each transaction gets hard limits to stop one bad piece of code from hurting everyone else. If you cross one, the platform throws an exception you can't catch and the whole transaction rolls back. The ones I watch most are 100 SOQL queries per synchronous transaction, 150 DML statements, 50,000 rows returned by queries, 10,000 records changed by DML, and CPU time, which is 10 seconds for synchronous code. Async Apex gets higher limits for some of these, like 200 queries and 60 seconds of CPU. In practice almost every limit error comes from the same mistake: a query or DML statement inside a loop, which works for one record in the UI and fails the moment someone loads 200. I check usage with the Limits class and the limit summary in the debug log, and I design for bulk from the start."

Red flag to avoid:

Treating limits as something to work around with try-catch, or not knowing the query and DML limits at all.

They may ask next:
  • Can you catch a LimitException in a try-catch block?
  • Which limits change when the same code runs in a batch job instead of a trigger?
Say it in 60 seconds
Medium Coding round Fresher, Mid-level Practice question

15. Write a trigger that fills a new contact's mailing country from its account, and make sure it works when 200 contacts are loaded at once.

What the interviewer is really testing:
Whether you write bulk-safe Apex by reflex: collect Ids, query once, use a map, and avoid needless DML.
Answer frame:

Collect: loop Trigger.new once and gather the account Ids that matter.

Query once: one SOQL query into a map keyed by Id.

Apply: set fields on Trigger.new in a before trigger, so no DML is needed.

Sample spoken answer:

"Bulkifying means the trigger behaves the same for one record or two hundred, with a fixed number of queries. First I loop over Trigger.new once and collect the account Ids I care about, skipping contacts with no account or that already have a country. Then I run a single query for all those accounts and put the results in a map keyed by Id. Then I loop again and copy the billing country onto each contact from the map. Because it's a before insert trigger, I'm changing the records that are about to be saved, so there's no update statement at all. The result is one query no matter how many contacts come in. In a real org I'd move this into a handler class and test it by inserting 200 contacts, but the pattern stays the same: collect, query once, map, apply."

Code:
trigger ContactTrigger on Contact (before insert) {
    Set<Id> accountIds = new Set<Id>();
    for (Contact c : Trigger.new) {
        if (c.AccountId != null && c.MailingCountry == null) {
            accountIds.add(c.AccountId);
        }
    }
    if (!accountIds.isEmpty()) {
        Map<Id, Account> accounts = new Map<Id, Account>(
            [SELECT Id, BillingCountry FROM Account WHERE Id IN :accountIds]
        );
        for (Contact c : Trigger.new) {
            Account a = accounts.get(c.AccountId);
            if (a != null && c.MailingCountry == null) {
                c.MailingCountry = a.BillingCountry;
            }
        }
    }
}
Red flag to avoid:

Querying the account inside the loop, or calling update on Trigger.new in a before trigger.

They may ask next:
  • How would you change this to also run when a contact moves to a different account?
  • Why don't you need an update statement here?
Say it in 60 seconds
Medium Technical round Mid-level, Senior Practice question

16. How do you structure triggers in a large org, and how do you stop a trigger from running itself in a loop?

What the interviewer is really testing:
Whether you know the one-trigger-per-object pattern and a recursion guard that doesn't silently skip records.
Answer frame:

One trigger per object: a logic-free trigger that calls a handler class per context.

Bypass: a custom setting or custom permission so data loads can skip automation safely.

Recursion: track processed record Ids in a static set and act only when relevant fields changed.

Sample spoken answer:

"I keep one trigger per object, and the trigger itself holds no logic. It hands off to a handler class, with a method for each context like before insert or after update. That gives me a predictable order, because Salesforce doesn't guarantee the order between two triggers on one object, and it keeps the logic testable and reusable. I also add a bypass switch, usually a custom setting or custom permission, so data loads can skip automation safely. For recursion, the classic case is an after update trigger that updates the same records, which fires the trigger again. The naive fix is a static Boolean flag, but that can skip records, because a large DML is processed in chunks of 200 within one transaction and the flag blocks the later chunks. So I track a static set of Ids already processed, and better still, only act when the fields I care about actually changed, by comparing with Trigger.oldMap."

Red flag to avoid:

Putting all logic in several triggers on the same object, or relying on a static Boolean that skips later chunks.

They may ask next:
  • Why does a static variable keep its value between trigger runs in the same transaction?
  • How would you let one integration user skip all automation on an object?
Say it in 60 seconds
Hard Technical round Mid-level, Senior Practice question

17. What causes a MIXED_DML_OPERATION error, and how do you fix it?

What the interviewer is really testing:
Whether you know the setup versus non-setup object split and the standard ways to separate the work into different transactions.
Answer frame:

Cause: DML on setup objects like Group, GroupMember or PermissionSetAssignment and on data objects in one transaction.

Fix in code: move one side into a queueable or future method, passing Ids.

Fix in tests: wrap the setup DML in System.runAs.

Sample spoken answer:

"Salesforce separates setup objects, like User, Group, GroupMember, UserRole and PermissionSetAssignment, from regular data objects like Account or Case. Changing a setup object can change who sees what, so the platform won't let you do DML on both kinds in the same transaction. A common example is a trigger on Opportunity that updates the record and also adds the owner to a public group, or onboarding code that assigns a permission set and then updates the account. The fix is to split the work into separate transactions. I keep the data changes where they are and move the setup change into a queueable or a future method, passing Ids rather than records. In test classes the same error shows up when a test creates setup records and data together, and there I wrap the setup work in a System.runAs block, which gives it its own context."

Red flag to avoid:

Catching the exception and ignoring it, or not knowing which objects count as setup objects.

They may ask next:
  • Why can't you pass sObjects into a future method?
  • What would you check if the async part fails after the main transaction has committed?
Say it in 60 seconds

Async Apex 3 questions

Medium Technical round Mid-level, Senior Practice question

18. Compare future methods, Queueable, Batch and Schedulable Apex. How do you pick one?

What the interviewer is really testing:
Whether you know the practical limits of each async tool and match it to the job instead of using one for everything.
Answer frame:

Future: simplest; primitive parameters only, no chaining, no job Id.

Queueable: complex types, a job Id to monitor, can chain the next job.

Batch: very large volumes in chunks, each chunk a fresh transaction.

Schedulable: runs on a cron schedule, often to start a batch.

Sample spoken answer:

"They all run later, in their own transaction with higher limits, but they fit different jobs. A future method is the simplest: a static void method marked @future, but it only accepts primitive parameters like Ids, I can't chain it, and I get no job Id to track. Queueable is what I reach for by default now. It takes complex types including sObjects, returns a job Id I can monitor, and a job can enqueue the next one, so I can chain steps. Batch Apex is for volume: it splits a huge set of records into chunks, and each chunk runs as its own transaction with fresh limits. Schedulable is about time: it runs a class on a cron schedule, usually just to kick off a batch every night. So small follow-up work after a save is queueable, huge data is batch, and a timetable is schedulable."

Red flag to avoid:

Using a future method per record inside a loop, or choosing batch for a single small follow-up task.

They may ask next:
  • Why can't a future method take an sObject as a parameter?
  • How many jobs can one queueable enqueue when it's already running asynchronously?
Say it in 60 seconds
Medium Coding round Mid-level, Senior Practice question

19. Write a batch job that closes every case nobody has touched in 90 days, and explain how its chunks and limits work.

What the interviewer is really testing:
Whether you can write the batch interface correctly and understand chunking, per-chunk transactions, partial success and state between chunks.
Answer frame:

Start: a query locator defines the records, up to fifty million.

Execute: once per chunk, 200 by default, each a separate transaction with its own limits.

Finish and state: finish runs once; Database.Stateful keeps instance variables across chunks.

Sample spoken answer:

"Batch Apex has three methods. Start defines the records, usually with a query locator, which can cover up to fifty million rows. Execute runs once per chunk, 200 records by default, and each chunk is a separate transaction with its own limits, so one failing chunk doesn't roll back the others. Finish runs once at the end, which is where I'd send a summary or chain the next job. Here I'm closing cases that haven't changed in ninety days. I use Database.update with allOrNone set to false so one record failing a validation rule doesn't sink its whole chunk, and I implement Database.Stateful so the counter survives between chunks, because without it instance variables reset for every chunk. I'd launch it with Database.executeBatch and schedule it nightly with a small Schedulable class."

Code:
public class CloseStaleCasesBatch implements Database.Batchable<SObject>, Database.Stateful {
    public Integer closedCount = 0;

    public Database.QueryLocator start(Database.BatchableContext bc) {
        return Database.getQueryLocator([
            SELECT Id, Status FROM Case
            WHERE IsClosed = false AND LastModifiedDate < LAST_N_DAYS:90
        ]);
    }

    public void execute(Database.BatchableContext bc, List<SObject> scope) {
        List<Case> cases = (List<Case>) scope;
        for (Case c : cases) {
            c.Status = 'Closed';
        }
        for (Database.SaveResult r : Database.update(cases, false)) {
            if (r.isSuccess()) closedCount++;
        }
    }

    public void finish(Database.BatchableContext bc) {
        System.debug('Closed ' + closedCount + ' cases');
    }
}
// Database.executeBatch(new CloseStaleCasesBatch(), 200);
Red flag to avoid:

Expecting instance variables to keep their values between chunks without Database.Stateful.

They may ask next:
  • Why might you lower the scope size below 200?
  • How would you report the records that failed to update?
Say it in 60 seconds
Hard Technical round Mid-level, Senior Practice question

20. A trigger on Account must send new customers to an external billing system. Why can't you call out from the trigger, and what do you do instead?

What the interviewer is really testing:
Whether you know the platform blocks synchronous callouts in triggers and can design a bulk-safe, secure, retryable async integration.
Answer frame:

Why: no synchronous callouts from triggers, and none after uncommitted DML in the same transaction.

How: collect Ids, enqueue one Queueable with Database.AllowsCallouts, or a future method with callout=true.

Robustness: Named Credential for the endpoint and auth, a status field, retries for failures.

Sample spoken answer:

"Salesforce doesn't allow a synchronous callout from a trigger, because the trigger runs inside the database transaction and holding it open while waiting on another system would lock records. More generally, you can't make a callout after uncommitted DML in the same transaction. So I move the callout out of the transaction. In the trigger I collect the Ids of the new accounts and enqueue one Queueable that implements Database.AllowsCallouts, or call a future method marked callout equals true. It's one job for the whole set of records, not one per record, because there's a limit on how many async jobs a transaction can start. The job queries the accounts fresh, sends them in one request if the API allows, uses a Named Credential so no endpoint or secret sits in code, and writes the result back to a status field, with a retry for failures."

Red flag to avoid:

Enqueuing one future call per record, or hard-coding the endpoint and password in Apex.

They may ask next:
  • How would you test this job without calling the real billing system?
  • What happens if the external system is down for an hour?
Say it in 60 seconds

Lightning Web Components 3 questions

Easy Technical round Fresher, Mid-level Practice question

21. What is a Lightning Web Component made of, and what do the @api, @wire and @track decorators do?

What the interviewer is really testing:
Whether you know the basic building blocks of LWC and the current meaning of the decorators, including that @track is rarely needed now.
Answer frame:

Standards: custom elements, shadow DOM and ES modules; mostly plain modern JavaScript.

Bundle: HTML template, a JavaScript class extending LightningElement, a meta XML file, optional CSS.

Decorators: @api public, @wire reactive data, @track only for deep mutation of objects or arrays.

Sample spoken answer:

"A Lightning Web Component is built on web standards: custom elements, shadow DOM and ES modules, so it's mostly plain modern JavaScript. The bundle is a folder with an HTML template, a JavaScript class that extends LightningElement, a meta XML file that says where it can be used, like record pages or app pages, and optionally a CSS file. For decorators, @api makes a property or method public, so a parent component or the Lightning App Builder can set it. recordId on a record page is the classic example. @wire connects a property or function to a data source, like an Apex method or a Lightning Data Service adapter, and re-runs when its reactive parameters change. @track is mostly not needed any more, since all fields are reactive. I only use it when I change a property inside an object or array and need the template to re-render."

Red flag to avoid:

Putting @track on every field, or not knowing what the meta XML file is for.

They may ask next:
  • Can you put a Lightning Web Component inside an Aura component, and the other way round?
  • Why shouldn't a child component change a property it received through @api?
Say it in 60 seconds
Medium Technical round Mid-level Practice question

22. In a Lightning Web Component, when do you use @wire to call Apex and when do you call it imperatively?

What the interviewer is really testing:
Whether you understand caching, reactivity and the cacheable rule, and can pick the right call style for reading versus changing data.
Answer frame:

Wire: automatic and reactive; needs cacheable=true, so no DML; data is read-only and cached.

Imperative: on user action or when the method changes data; returns a promise.

Keep in sync: refreshApex on the wired result after a change.

Sample spoken answer:

"With @wire, the framework calls the method for me when the component loads and again whenever a reactive parameter changes, like recordId with a dollar prefix. The Apex method has to be marked cacheable=true, which also means it can't do DML, and the data I get back is read-only and may come from cache, so I call refreshApex when I know it's stale. That's ideal for simply showing data. I call Apex imperatively when I need control over timing: on a button click, after validating input, or whenever the method changes data, since that can't be cacheable. An imperative call returns a promise, so I await it and handle errors in a try-catch. Here the open cases are wired from the record Id, and closing a case is an imperative call from the button handler, followed by refreshApex so the list updates."

Code:
import { LightningElement, api, wire } from 'lwc';
import { refreshApex } from '@salesforce/apex';
import getOpenCases from '@salesforce/apex/CaseController.getOpenCases';
import closeCase from '@salesforce/apex/CaseController.closeCase';

export default class AccountCases extends LightningElement {
    @api recordId;
    error;

    @wire(getOpenCases, { accountId: '$recordId' })
    cases;

    async handleClose(event) {
        try {
            await closeCase({ caseId: event.target.dataset.id });
            await refreshApex(this.cases);
        } catch (e) {
            this.error = e.body ? e.body.message : e.message;
        }
    }
}
Red flag to avoid:

Trying to do DML from a cacheable method, or editing wired data in place.

They may ask next:
  • Why does changing a field on a wired record throw an error, and how do you work around it?
  • When would you use a Lightning Data Service adapter instead of Apex?
Say it in 60 seconds
Medium Technical round Fresher, Mid-level Practice question

23. How do Lightning Web Components talk to each other, parent to child, child to parent, and between unrelated components on one page?

What the interviewer is really testing:
Whether you know the right channel for each relationship and don't reach for a global workaround when a property or event would do.
Answer frame:

Parent to child: public @api properties or methods.

Child to parent: dispatch a CustomEvent; the parent listens with an on handler in markup.

Unrelated: Lightning Message Service over a message channel, which also reaches Aura and Visualforce.

Sample spoken answer:

"It depends on how the components are related. Parent to child is the simplest: the child exposes a property or a method with @api, and the parent sets the property in its template or calls the method on the child element. Child to parent goes the other way with events. The child creates a CustomEvent, say select, with the record Id in the detail, and dispatches it. The parent listens with onselect on the child's tag. Event names are lowercase with no on prefix, and I keep them from bubbling unless I really need that. For components that aren't in the same tree, like two separate components dropped on one Lightning page, I use Lightning Message Service. I define a message channel, one component publishes and the other subscribes, and it works across Aura and Visualforce too. I'd avoid the old pubsub module in new work."

Red flag to avoid:

Having a child change its parent's data directly, or using a message channel between a parent and its own child.

They may ask next:
  • What's the difference between bubbles and composed on a custom event?
  • When do you need to unsubscribe from a message channel?
Say it in 60 seconds

Deployment & Testing 3 questions

Easy Technical round Fresher, Mid-level, Senior Practice question

24. How do change sets compare with Salesforce DX for moving work to production? Which would you use?

What the interviewer is really testing:
Whether you've shipped beyond one sandbox and understand version control, repeatable deployments and the limits of change sets.
Answer frame:

Change sets: point and click between connected orgs; no deletions, no history, easy to miss dependencies.

Salesforce DX: source in Git, Salesforce CLI, scratch orgs or sandboxes, CI pipelines, destructive changes.

Production: validate first, then quick deploy in the release window.

Sample spoken answer:

"Change sets are the point-and-click way: I build an outbound change set in a sandbox, add components by hand, upload it to a connected org and deploy it there. They're fine for a small admin change, but they only move between orgs linked to the same production, they can't delete components, there's no version history, and it's easy to forget a dependency. With Salesforce DX the source of truth is a Git repository. I work in a scratch org or sandbox, pull the metadata into source format with the Salesforce CLI, commit it, open a pull request, and a pipeline validates and deploys it. That gives me code review, a record of every change, deletions through a destructive changes manifest, and deployments I can repeat. DevOps Center puts a UI on the same Git-based flow for admins. For production I validate first, then quick deploy in the release window."

Red flag to avoid:

Making changes directly in production because the deployment process feels slow.

They may ask next:
  • What's the difference between a scratch org and a sandbox?
  • How would you remove a field from production using the CLI?
Say it in 60 seconds
Medium Technical round Fresher, Mid-level, Senior Practice question

25. What test coverage does production require for Apex, and what makes a test class actually good rather than just covering lines?

What the interviewer is really testing:
Whether you know the deployment rule and write tests that prove behaviour in bulk, negative and permission cases, not just chase a number.
Answer frame:

The rule: at least 75 percent org-wide coverage, all tests passing, and some coverage for every trigger.

Good data: own test data via @testSetup or a factory, never real org data.

Real checks: bulk and negative cases, System.runAs, Test.startTest and stopTest, mocks, assertions.

Sample spoken answer:

"To deploy Apex to production, the org needs at least 75 percent of its Apex lines covered by tests overall, the tests have to pass, and every trigger needs some coverage. But I treat that number as a floor, not the goal. A good test proves behaviour. I create my own data, usually in a @testSetup method or a test data factory, rather than relying on org data. I test in bulk, with 200 records, to catch queries inside loops. I test the negative path, like a save that should fail, and I run as a restricted user with System.runAs when sharing matters. I wrap the action in Test.startTest and Test.stopTest, which gives fresh limits and makes async jobs finish at stopTest, so I can assert on their results. Callouts get a mock through Test.setMock. And every test ends with real assertions about the outcome."

Red flag to avoid:

Writing tests with no assertions just to reach the coverage number.

They may ask next:
  • Why is SeeAllData=true a bad habit?
  • How would you test a queueable that makes a callout?
Say it in 60 seconds
Medium Situational round Mid-level, Senior Practice question

26. It's release night and your production deployment fails because tests in classes you never touched are failing. What do you do?

What the interviewer is really testing:
Whether you stay calm, find the real cause, make a clear go or no-go call, and fix the process rather than hacking tests to pass.
Answer frame:

Don't force it: no commenting out assertions, no skipping tests to get green.

Find the cause: usually a change made directly in production that breaks old test data.

Decide and prevent: go only if fixed and re-validated in the window; validate days ahead next time.

Sample spoken answer:

"First, I don't try to force it through, and I don't comment out assertions to get green. I'd read the failures. Very often the cause is something changed directly in production, like a new validation rule or required field, that breaks the test data those old tests create. Or a test depends on real org data that has changed. I'd check whether the fix is small and safe, like updating a test data factory, and whether I can validate it quickly. Then I'd make the call with the release owner: if we can fix and re-validate within the window, we go; if not, we postpone rather than ship something half tested. Either way I'd raise the root cause: we should validate the deployment days before release night, run all tests on a schedule so failures show up early, and stop unreviewed changes going straight into production."

Red flag to avoid:

Deleting or disabling the failing tests to get the release out.

They may ask next:
  • When is running only specified tests in a production deployment acceptable?
  • How would you stop admins from making changes directly in production without slowing them down?
Say it in 60 seconds

Solution Design 1 questions

Hard Case round Mid-level, Senior Practice question

27. Sales asks: when a deal is Closed Won, create an onboarding record for delivery, lock the amount except for sales ops, and let delivery managers see won deals in their region only. How would you build it?

What the interviewer is really testing:
Whether you can turn a business request into data model, automation, validation and sharing choices, with the simplest correct tool for each part.
Answer frame:

Clarify: what onboarding needs, who sales ops are, how region is stored.

Build: a custom object with a lookup, an after-save flow on the stage change, a validation rule with a custom permission.

Access: private opportunities plus criteria-based sharing rules per region.

Prove: test in a sandbox as each type of user, then deploy together.

Sample spoken answer:

"First I'd confirm the details: what an onboarding record needs, who counts as sales ops, and how region is stored on the deal. For the data model, I'd create an Onboarding object with a lookup to Opportunity, not master-detail, because delivery needs to own those records themselves. For creation, an after-save record-triggered flow on Opportunity that runs only when the stage changes to Closed Won, creates the onboarding record and assigns it to the delivery queue. For the lock, a validation rule that fires when the previous stage was Closed Won and the amount changes, unless the user has a custom permission, which I'd give sales ops through a permission set. For visibility, with opportunities private by default, I'd add criteria-based sharing rules, one per region, sharing Closed Won deals read-only with that region's delivery group. Then I'd test it in a sandbox as each type of user and deploy it as one release."

Code:
AND(
  ISPICKVAL(PRIORVALUE(StageName), "Closed Won"),
  ISCHANGED(Amount),
  NOT($Permission.Edit_Won_Amount)
)
Red flag to avoid:

Jumping straight to an Apex trigger for all three parts, or giving delivery managers View All on opportunities.

They may ask next:
  • What if a deal is reopened and closed again: how do you avoid a second onboarding record?
  • How would your sharing design change if regions were added every quarter?
Say it in 60 seconds

Real Work 3 questions

Medium Behavioral round Mid-level, Senior Practice question

28. Tell me about a time a governor limit error hit production. How did you find the cause and fix it?

What the interviewer is really testing:
Whether you have debugged a real limit failure with logs, fixed the root cause in bulk-safe code and changed the team's habits afterwards.
Answer frame:

Situation: what failed, for whom, and why it was urgent.

Diagnosis: the debug log, the limit summary, the loop that caused it.

Fix and lesson: the bulk-safe rewrite, a 200-record test, and the process change.

Sample spoken answer:

"At my last company, the sales ops team ran a monthly import of about five thousand accounts through a data loader, and one month it started failing with too many SOQL queries. Nothing had changed in the import itself, so I pulled a debug log for the integration user and read the limit summary. A developer had added a helper that looked up the territory for each account, and it ran a query inside a loop. In the UI, one record at a time, it was fine. At 200 records per chunk it went past a hundred queries. I refactored it to collect all the territory keys first, query once into a map, and then assign. I added a test that inserts 200 accounts and checks the result, and the next import ran clean. After that we added a bulk test to our code review checklist."

Red flag to avoid:

A story where the fix was raising a limit, splitting the file smaller, or turning the automation off for good.

They may ask next:
  • How did you make sure the fix didn't change which territory each account got?
  • What would you have done if the import had to run that same day?
Say it in 60 seconds
Medium Behavioral round Fresher, Mid-level, Senior Practice question

29. Tell me about a time you talked a stakeholder out of custom development because standard configuration could do the job.

What the interviewer is really testing:
Whether you know the platform's standard features well enough to push back politely, and can win the stakeholder over with something they can see.
Answer frame:

Request: what was asked for and what it would have cost to build.

Real need: the questions that uncovered what the business actually needed.

Outcome: the standard solution, how you showed it, and what the saved effort went to.

Sample spoken answer:

"A sales director once asked for a custom Lightning page to approve large discounts, with its own screen, email alerts and a history log, and the estimate was a few weeks of developer time. When I sat with him and walked through what he actually needed, it came down to this: deals above a certain discount go to the regional manager, then finance, with a record of who approved and when. That's exactly what a standard approval process does, with a flow for the notifications. I built a working version in a sandbox in two days and showed it to him using his own deals. He wanted one extra field on the approval screen, which was a simple layout change. It went live the next week, admins could maintain it without developers, and the developer time went to an integration that genuinely needed code."

Red flag to avoid:

A story where you simply refused the request without showing an alternative.

They may ask next:
  • What would you have done if he had insisted on the custom page anyway?
  • When is custom code the right answer even though a standard feature exists?
Say it in 60 seconds
Hard Behavioral round Senior Practice question

30. Walk me through a Salesforce org you inherited with messy automation. How did you clean it up without breaking the business?

What the interviewer is really testing:
Whether you can reduce technical debt safely: map before changing, agree a target pattern, migrate in small tested steps and measure the result.
Answer frame:

The mess: what ran on the object and the symptoms users felt.

Map first: an inventory of every automation and its real order from logs.

Migrate safely: a target pattern, small releases, tests pinning old behaviour, a bypass switch.

Sample spoken answer:

"At my last job I inherited an org where the Opportunity object had two triggers, four Process Builders, a couple of old workflow rules and three flows, built by different people over years. Users were hitting CPU time limit errors on big deals, and some fields were overwritten by one automation after another. I didn't start by rewriting. First I mapped every automation on the object, what it touched and when, and checked debug logs to see the real order. Then I agreed a target with the team: one trigger with a handler class for the heavy logic, and before-save flows for simple field updates. I migrated in small releases, one process at a time, each with tests that pinned the old behaviour, and I added a bypass switch for data loads. Over about two months the CPU errors stopped, the overwrites went away, and changes took hours instead of days."

Red flag to avoid:

A big-bang rewrite of everything in one release, with no tests of the old behaviour.

They may ask next:
  • How did you handle a piece of automation nobody could explain?
  • How did you convince the business to accept releases with no visible new features?
Say it in 60 seconds
Were you asked something else? Share it A person checks every question before it goes on the site. No name is shown.
For the call itself

The questions above are the prep. The call has ten more.

ClapAssist is an AI interview assistant for Mac and Windows. It listens to the interview on your computer and shows you what to say, in short lines you can read while you talk. Your resume and notes are never stored on our servers. It stays out of screen share on every plan; only you can see it.

Download ClapAssist with 10 free minutes
Mac and Windows · Stays out of screen share · No card