Back to Blog
Salesforce

7 Salesforce Questions That Fool Senior Developers

TS

Tushar Sharma

Chief Executive Officer

11 min read - Oct 23, 2026

The short version

  • These are seven real questions, verbatim, from our free 87-question Salesforce Developer Quiz, chosen because experienced developers miss them most, and each one fails for a specific, learnable reason.
  • The pattern across all seven: certification knowledge describes what the platform offers; these questions test what the platform does, at the boundaries where documentation gets skimmed.
  • The recurring traps: rollbacks that give nothing back, triggers that quietly fire twice, lifecycle order that runs earlier than you think, events that outlive their transaction, and change events that are sparser than they look.
  • Every question on the quiz explains why the tempting answer fails, not just which letter was right, so a miss teaches a mechanism instead of a fact.
  • If you clear all seven comfortably, the other 80 are waiting, timed, free, no signup.

Why These Seven

We publish a free Salesforce Developer Quiz: 87 timed questions written by our consultants to test what the platform actually does, not what the certification guide says it offers. The scoring data has a pattern: a handful of questions fool experienced developers far more than the rest, and they all sit at the same kind of boundary, where day-to-day work quietly builds the wrong intuition. Here are seven of them, verbatim, with the mechanism behind each. Try answering before reading the resolution; that is the whole point.

1. The Rollback That Gives Nothing Back

Plain Anonymous Apex, no prior DML in the transaction. Two questions in one: what does the debug print, and what happens at the final insert?

APEX

Account a = new Account(Name = 'A1');
Savepoint sp = Database.setSavepoint();
insert a;
Database.rollback(sp);
System.debug(Limits.getDmlStatements());
insert a;

The tempting read: rollback undid the insert, so the counter is low and the record is free to insert again. The platform disagrees twice. The debug prints 3, because setSavepoint, insert, and rollback each count against the DML statement limit, and rollback never refunds consumption. And the second insert throws, because rollback removes the row from the database but never touches the in-memory variable: `a.Id` is still populated, and inserts cannot specify an Id. After a rollback, clone the record or null the Id before re-inserting.

2. The Trigger That Fires Twice Behind Your Back

A before-insert trigger counts its own firings and the records it sees. Three Contacts go in through a partial-success save; the middle one is missing its required LastName. No other automation in the org. What does the debug print?

APEX

// Trigger, before insert on Contact:
trigger CTrig on Contact (before insert) {
  Counter.fires++;
  Counter.seen += Trigger.new.size();
}
// Anonymous Apex (Counter has static Integer fires = 0, seen = 0):
List<Contact> cs = new List<Contact>{
  new Contact(LastName = 'A'),
  new Contact(),
  new Contact(LastName = 'B')
};
Database.insert(cs, false);
System.debug(Counter.fires + '/' + Counter.seen);

The most common belief is `1/3`: allOrNone=false just drops the bad record from the results. The real answer is `2/5`. Required-field validation runs after before triggers, so the first attempt fires the trigger with all three records; the failure then makes the runtime roll back that attempt and re-execute the save with only the two clean records, firing the trigger a second time. Three plus two is five, across two firings, in one transaction, which also means the static counters survive both rounds. This re-fire is exactly why naive static recursion guards misbehave under partial success.

3. Where Test.startTest Limits Actually End

The synchronous limit in this context is 100 SOQL queries per transaction. Walk the counts: 99 queries before startTest, 100 inside the block, 2 after stopTest. What happens?

APEX TEST

@isTest
static void limitBoundaries() {
  for (Integer i = 0; i < 99; i++) {
    List<Account> a = [SELECT Id FROM Account LIMIT 1];
  }
  Test.startTest();
  for (Integer i = 0; i < 100; i++) {
    List<Account> a = [SELECT Id FROM Account LIMIT 1];
  }
  Test.stopTest();
  List<Contact> c1 = [SELECT Id FROM Contact LIMIT 1];
  List<Contact> c2 = [SELECT Id FROM Contact LIMIT 1];
}

The trap is believing startTest resets limits for everything that follows. It does not: the fresh limits exist only between startTest and stopTest, where the 100 queries fit exactly. When stopTest runs, execution resumes the original context, which has already consumed 99 of its 100 queries. The first Contact query is number 100 and squeaks through; the second is number 101 and throws an uncatchable LimitException, after stopTest. The setup queries and the block never mix; the setup queries and the teardown queries absolutely do.

4. The LWC Setter That Runs Before You Think Anything Runs

A parent renders `<c-badge label="1042">`. The child computes its label in an @api setter using a prefix that connectedCallback sets. What does the badge display on first paint?

LWC

// parent template: <c-badge label="1042"></c-badge>
// badge.html: <template><p>{label}</p></template>
export default class Badge extends LightningElement {
  _label;
  prefix;
  @api
  get label() { return this._label; }
  set label(value) {
    this._label = this.prefix + value;
  }
  connectedCallback() {
    this.prefix = 'SKU-';
  }
}

The tempting answer leans on a true fact: connectedCallback really does run before the first render, so surely the prefix is set in time. But the engine constructs the child, assigns public properties first, and only then calls connectedCallback. The setter runs while `prefix` is still undefined and stores the string undefined1042 in `_label`. The template then reads the getter, which returns the already-computed value and never touches `prefix` again; nothing ever re-runs the setter, so no later render corrects it. Derive in the getter, or guard the setter, but never let a setter depend on lifecycle state.

5. The Event That Outlives Its Transaction

An audit event is published with behavior Publish Immediately. Then a downstream call throws, and the whole transaction rolls back. What is the end state?

APEX

public class EscalationService {
  public static void escalate(Id caseId) {
    update new Case(Id = caseId, Status = 'Escalated');
    EventBus.publish(new Audit_Event__e(
      Detail__c = 'Escalated ' + caseId
    ));
    RiskService.score(caseId); // throws an uncaught exception
  }
}

Most developers answer that the event rolls back with everything else, because EventBus.publish feels like DML. With Publish Immediately it is not: the event is handed to the bus the moment publish returns, independent of whether the transaction commits. The Case update rolls back; the event survives; subscribers receive an audit record for an escalation that never persisted. The roll-back-together behavior people expect is Publish After Commit, which is the default for exactly this reason. Choose the behavior per event, deliberately, not by whichever the picklist offered first.

6. The Change Event That Is Emptier Than It Looks

Change Data Capture is on for Account. A user changes `Name` and clears `Phone`, leaving `Industry` untouched. Considering all future Account updates, what does this subscriber actually do?

APEX CDC

trigger AccountChangeTrigger on AccountChangeEvent (after insert) {
  for (AccountChangeEvent ev : Trigger.new) {
    EventBus.ChangeEventHeader hdr = ev.ChangeEventHeader;
    if (hdr.changeType == 'UPDATE' && ev.Phone == null) {
      NotificationService.phoneCleared(hdr.recordIds);
    }
  }
}

The assumption that sinks this one: UPDATE change events carry the current value of every field. They do not. Only the changed fields are populated; every untouched field arrives as null, so `ev.Phone == null` is true on nearly every Account update, and this trigger spams notifications for edits that never went near Phone. A field genuinely cleared to null is flagged in the header’s `nulledFields` list, which exists precisely because a real null and an absent field are otherwise indistinguishable in the payload. (And `diffFields` is unrelated: it marks large text fields shipped as diffs.)

7. One Method to Mock Them All

The Stub API hands you a single dispatch point for an entire class. How do you return method-specific mock values from one handleMethodCall?

APEX STUB API

public class Mock implements System.StubProvider {
  public Object handleMethodCall(Object obj, String method,
      Type returnType, List<Type> paramTypes,
      List<String> paramNames, List<Object> args) {
    return /* mocked value */;
  }
}

Developers who have only used mocking frameworks sometimes conclude you must implement each method individually, or that one dispatch point cannot know what was called. The signature says otherwise: handleMethodCall receives the invoked method name, its return and parameter types, the parameter names, and the live arguments. Branch on `method` (and inspect `args` when overloads matter), return the value for that call, and one class mocks the entire interface. It is the lowest-level, most honest mocking tool the platform has, and the Stub API section of the quiz is where scores drop hardest.

The Other 80 Are Waiting

If you answered all seven cold, respect, and the full quiz will still find your gaps: 87 questions, timed, shuffled every run, free, no signup, with an explanation behind every wrong answer so a miss teaches a mechanism. Your best score saves locally, the results break down by topic, and the share line includes your time, so bring evidence when you claim senior.

Teams use it too: as an interview calibration bar and as a warm-up before architecture reviews. And if the quiz surfaces gaps you would rather close with the people who wrote it, our Salesforce practice is a free 30-minute call away.

Free 30-minute consultation

Want this working in your org?

Tell us where to send times and prep notes. You get a senior architect and an honest read on scope and cost, not a sales pitch.

No spam, no list. One architect, one email, that is it.

FAQ

Frequently Asked Questions

Where do these questions come from?

They are taken verbatim from the Salesforce Developer Quiz we publish free at cloudsheer.com/salesforce-dev-quiz: 87 questions our consultants wrote to pressure-test senior platform knowledge, heavy on Apex internals, LWC lifecycle, test mechanics, Platform Events, Change Data Capture, and the Stub API. These seven are the ones experienced developers miss most often.

How hard is the full quiz?

Deliberately hard: it is not a certification dump, and every question asks you to predict actual platform behavior rather than recall a feature name. Three is a respectable score per ten for a working developer; clearing 75 percent puts you in senior territory by the bar we hire against. The timer is part of the fun, and your best score saves locally.

Can I retake the quiz?

As often as you like, free, no signup. The question order and answer positions shuffle every run, so a retake is a genuine retest rather than memory of letter positions, and your best score is kept locally on your device.

Can teams use the quiz for interviews?

Teams already do: it works as an interview calibration bar and as a pressure test before architecture reviews. The per-topic breakdown on the results screen shows exactly where a candidate or a team is strong and where the gaps sit, which is more useful than a single number.

Why do senior developers miss these specific questions?

Because each sits at a boundary where everyday experience builds the wrong intuition: partial-success saves rarely fail in dev orgs, so the re-fire behavior goes unseen; startTest limits are usually generous enough that the outer context never bites; Publish Immediately versus Publish After Commit only matters the day a rollback happens. The platform behaves consistently; the intuition is what drifts.

Want to see how this applies to your business?

Book a free 30-minute call. We will walk through your specific use case and show you what's possible.

Book Free Discovery Call
Ask me anything