Short Notes Salesforce interview Questions and Answers Summary
By GetItFullyโขโข95 min read

1/16
Salesforce Interview Notes · Lead / Architect
★ARCHITECTURE & DESIGN PATTERNS★
Skew, big objects, trigger frameworks, LDV, migration
โ ๏ธData Skew
- Skew = too many child/related records tied to ONE parent record
- Causes record-locking errors + slow queries + sharing recalc pain
- Account skew: >10,000 child records (Contacts/Cases/Opps) on one Account
- Ownership skew: >10,000 records of one object owned by one user
- Lookup skew: >10,000 records pointing at same lookup target value
- Classic symptom: Approval Process waiting on manager ⟶ parent row lock
- Parent lock cascades: updating child locks the parent record
- Fixes: distribute across parents, "bucket" accounts, integration user w/ no role
- Ownership skew fix: put owner OUTSIDE role hierarchy, no public groups
- Also: reduce batch size to 1, sort by ParentId to avoid concurrent locks
๐๏ธBig Objects
- Stores billions of records outside standard object storage
- Standard big object = FieldHistoryArchive (field history archival)
- Custom big object suffix __b; defined by index at creation time
- Index: up to 5 fields, queried LEFT-TO-RIGHT, cannot skip fields
- Index is IMMUTABLE after deploy ⟶ redesign = new object
- No triggers, flows, validation rules, process builder on big objects
- Insert via Apex insertImmediate(), Bulk API, or CSV import
- Read via SOQL on index fields only; Async SOQL for bulk analytics
- Use for: audit trails, IoT/event history, 360 archive, compliance
๐งฉTrigger Frameworks
- Goal: ONE trigger per object, zero logic in the trigger body
- Trigger Handler pattern: Apex class holds all logic, trigger just delegates
- Virtual base class: overridable beforeInsert(), afterUpdate() hooks
- Interface-based: handlers implement common interface (rare in practice)
- Handler dispatches on Trigger.isBefore / isAfter / isInsert context
- Recursion control: static Boolean / Set<Id> of processed record Ids
- Bypass switch: Custom Metadata or hierarchy Custom Setting per handler
- Keep logic bulkified: no SOQL/DML inside for loops
- Popular: Kevin O'Hara sfdc-trigger-framework, fflib Domain layer
โ๏ธTrigger vs Declarative
- Default: Flow first โ declarative is the platform direction
- Record-Triggered Flow replaced Workflow Rules + Process Builder (retired)
- Use Apex trigger for: complex logic Flow cannot do
- Apex needed for: custom error handling, redirects, callouts pre-commit
- Apex needed for: cross-object rollups w/o master-detail, recursive logic
- Apex needed for: large-volume bulk processing, complex sorting/matching
- Don't mix Flow + trigger on same object/same operation ⟶ order chaos
- Before-save Flow is ~10x faster than Process Builder (no extra DML)
๐Large Data Volumes
- Batch Apex + Scheduled Apex to process records asynchronously
- Batch scope default 200, max 2000; 5 concurrent batch jobs
- Selective SOQL is mandatory: filter on indexed field
- Standard index selective: <30% of first 1M rows, <15% after, cap 1M
- Custom index selective: <10% of rows, hard cap 333,333 rows
- Skinny tables: read-only denormalized copy, max 100 columns, no joins
- Avoid NULL / != / NOT / leading-wildcard LIKE ⟶ kills index
- Divisions partition very large orgs; Custom Indexes via Salesforce support
- PK Chunking for Bulk API extracts of huge objects
- Defer sharing recalculation during mass loads
- Change Data Capture to propagate changes out, not nightly full pulls
- Archive cold data to Big Objects or external store (Salesforce Connect)
๐One-Time Migration
- Tooling: Data Loader / ETL (Informatica, MuleSoft) over Bulk API
- Bulk API 2.0: 150M records / 24 hrs; auto-chunked server-side
- Load PARENTS before children; use External Id as match key
- External Id upsert avoids extra lookup queries + duplicate rows
- Deactivate triggers, flows, validation rules, workflow during load
- Load in parallel batches; serial mode if you hit lock contention
- Sort file by parent Id to prevent concurrent parent locks
- Defer sharing calc + turn off role hierarchy grants if possible
- Re-enable automation, then reconcile record counts + error files
- Dry-run in Full sandbox first; capture success/error CSVs
๐ก๏ธException Framework
- Custom logging object e.g. ACE_Exception_Log__c stores exception details
- Capture: class, method, line, getStackTraceString(), record Ids, user
- Wrap logic in try/catch; never swallow silently, always log
- Log DML with allOrNone=false ⟶ Database.SaveResult errors captured
- Publish Platform Event for logging so log survives a rollback
- Custom exception: class MyException extends Exception
- addError() on record for user-facing validation failure
- Dashboard/report on log object + alert on severity
๐๏ธMVC & Conventions
- Model = objects, fields, relationships (the data layer)
- View = LWC, Aura, Visualforce page, Lightning App Builder
- Controller = Apex class holding business logic
- Naming: CamelCase Java style; PascalCase classes, camelCase methods
- Suffix by role: XController, XService, XSelector, XHandler, XTest
- Data Warehouse = consolidate transactional data centrally for analysis
- SF is source system ⟶ warehouse (Snowflake/BigQuery) for cross-system BI
- Integration design phases: discover ⟶ data model ⟶ pattern ⟶ security ⟶ volume ⟶ error handling ⟶ cutover
⇄ Quick Comparison ⇄
Skew Types & Thresholds
| Skew Type | Threshold | Primary Fix |
|---|---|---|
| Account (data) skew | >10,000 children per Account | Distribute across parent buckets |
| Ownership skew | >10,000 records one owner | Owner outside role hierarchy |
| Lookup skew | >10,000 records same lookup value | Spread values / reduce automation |
| Symptom | UNABLE_TO_LOCK_ROW | Batch size 1, sort by ParentId |
Flow vs Apex Trigger
| Record-Triggered Flow | Criterion | Apex Trigger |
|---|---|---|
| Declarative, admin-owned | Skill needed | Code, dev + test class |
| Simple field updates, rollups | Best for | Complex, bulk, recursive logic |
| Limited, per-element faults | Error handling | Full try/catch + custom errors |
| Slower at high volume | LDV performance | Bulkified, best for millions |
| Before-save = fastest option | Speed | Fast, but needs discipline |
Easy way to remember
SKEW = 10K is the magic number for all three types
ONE trigger per object, ZERO logic inside it
Migration: Parents first, automation OFF, External Ids as keys
ONE trigger per object, ZERO logic inside it
Migration: Parents first, automation OFF, External Ids as keys
Interview tips
Q. What number defines data skew?
A. 10,000 โ child records per parent, records per owner, or per lookup value.
Q. Name a standard Big Object.
A. FieldHistoryArchive. Index is set at creation and can never be changed.
Q. Trigger or Flow?
A. Flow by default; Apex for complex bulk logic, callouts, and real error handling.
Takeaway
Design for the 10,000-record cliff โ skew, selectivity, and one clean trigger handler are what separate Lead from Senior.
💡 Read → Recall out loud → Explain to someone → Answer in the room
2/16
Salesforce Interview Notes · Lead / Architect
★SALESFORCE INTEGRATION★
Patterns, APIs, auth, callout limits, events
๐6 Integration Patterns
- Remote Process Invocation - Request & Reply: SF calls out, waits, tracks state
- Remote Process Invocation - Fire & Forget: remote acks, control returns immediately
- Batch Data Synchronization: bulk both directions, scheduled, not real time
- Remote Call-In: external system does CRUD on SF data (inbound)
- UI Update Based on Data Changes: SF UI auto-refreshes on data change
- Data Virtualization: real-time external read, no persistence, no reconciliation
- Virtualization = Salesforce Connect + external objects (OData 2.0/4.0 or Apex adapter)
- Fire & Forget best implemented with Platform Events, not a callout
โฑ๏ธCallout Limits
- 100 callouts per Apex transaction (sync + async combined)
- Default timeout 10 seconds per callout; max settable 120 seconds
- 120 seconds cumulative timeout for ALL callouts in one transaction
- API calls: ~250,000 / 24h on Professional + Enterprise (buy more)
- @ReadOnly doubles query rows to 1,000,000 - read-only endpoints
- SOQL in REST endpoints: LIMIT 50000 rows max
- Messaging.sendEmail 10x per transaction; 5,000 single emails/day
- 225,000 workflow emails/day - avoid emailing from integration code
๐Named Creds vs Remote Site
- Named Credential = endpoint URL + auth (user/pass, OAuth token) in one
- Remote Site Setting = whitelist only, no credentials stored
- Callout syntax: req.setEndpoint('callout:My_Named_Cred/services/data/v58.0/...')
- Named Credential ⟹ no secrets in code, no Remote Site entry needed
- Remote Site still required for raw https:// endpoints + WSDL2Apex stubs
- Endpoint in a Custom Label = per-environment switching without deploy
๐OAuth + Auth Flows
- Flows: Web Server, User-Agent, JWT Bearer, Username-Password, Refresh Token, Device
- OAuth = grant access without sharing passwords; used by Connected Apps
- Connected App: SAML + OAuth, SSO, tokens, IP relaxation, refresh token policy
- JWT Bearer = server-to-server, no user interaction, cert on connected app
- JWT: POST to /services/oauth2/token, grant_type=urn:ietf:params:oauth:grant-type:jwt-bearer
- Returns access_token + instance_url ⟶ always use returned instance_url
- Pass JWT in Authorization: Bearer header (preferred) not query string
- Query-string tokens leak into logs, browser history, referrer headers
- Postman password flow: username, password+token, client_id, client_secret, grant_type=password
๐ฅApex REST (Inbound)
- @RestResource(urlMapping='/MyService/*') - class must be global, path mandatory
- URI always /services/apexrest/<mapping>/
- @HttpGet select | @HttpPost create/upsert | @HttpPut insert-or-replace
- @HttpPatch update | @HttpDelete delete
- Each verb annotation may appear only ONCE per class
- RestRequest req = RestContext.request; RestContext.response for output
- RestRequest holds requestBody, params, headers, requestURI
- Response: RestContext.response.responseBody = Blob.valueOf(jsonStr)
- REST in SF is stateless, XML + JSON supported, JSON is default
๐คOutbound Callout
- Http h = new Http(); HttpRequest req; h.send(req) ⟶ HttpResponse
- setEndpoint / setMethod / setHeader('Content-Type','application/json') / setBody
- Build body with JSON.serialize(wrapper), never string concatenation
- JSON.deserializeUntyped ⟶ Map<String,Object>; JSON.deserialize(body, Wrapper.class) when typed
- No callouts inline from a trigger - callout blocks the transaction
- Use @future(callout=true) or Queueable + Database.AllowsCallouts
- @future takes primitives only - pass Ids as Strings, re-query inside
- Static Boolean flag stops recursion when callout result updates same records
- Bulkify: collect Ids in trigger, ONE async call, not one per record
- Test callouts with a mock class holding the canned response
๐กEvents + Streaming
- Pub/sub on the event bus; publisher + subscriber fully decoupled
- Publish via EventBus.publish(), Flow, or external API - a publish is NOT a callout
- Subscribe: Apex triggers, Flow, LWC empApi, external CometD clients
- Platform Event: retained 24-72 hours, replayable by ReplayId
- CDC: near real-time create/update/delete/undelete, retained 3 days
- CDC channel: /data/AccountChangeEvent, /data/Employee__ChangeEvent, /data/ChangeEvents (all)
- CDC perms: View All Data + View All Users for /data/ChangeEvents
- Streaming API PushTopic = notifications from a SOQL query you define
- Don't use events for synchronous response or guaranteed ordered request/reply
๐ก๏ธError Handling
- Savepoint sp = Database.setSavepoint(); Database.rollback(sp) in catch
- Database.insert(list, false) / Database.upsert() = partial success allowed
- Loop SaveResult[], isSuccess() false ⟶ log to API_Error_Log__c
- ALWAYS set a response body - success path AND failure path
- Wrap the whole method in try/catch; return JSON error, never a raw stack
- Log every call (request + response + status) to an Integration_Tracker__c
- Flow fault path ⟶ Integration_Log__c + notify integration team
- Test endpoints from Workbench REST Explorer or Postman
๐๏ธMuleSoft + Volume
- MuleSoft = Java ESB: routing, JDBC, DataWeave, API management, connectors
- Connects to SF via Anypoint Platform Salesforce Connector
- Heroku = PaaS for hosting apps, NOT an integration platform - you code it yourself
- Huge volumes: Bulk API (async, batched) over row-by-row REST/SOAP
- Big Objects for storage without standard data storage; Batch Apex to process
- Data Loader uses Bulk API for insert/update/upsert/delete/export
- View-only external data ⟶ Salesforce Connect, zero storage consumed
⇄ Quick Comparison ⇄
REST vs SOAP API
| REST API | Aspect | SOAP API |
|---|---|---|
| URI / URL resources | Addressing | WSDL contract |
| JSON (default) + XML | Format | XML only |
| Stateless, loosely typed | Typing | Strongly typed (Enterprise WSDL) |
| GET POST PATCH PUT DELETE HEAD | Verbs | Single POST envelope |
| Mobile, web, lightweight | Best for | Legacy, middleware, contract-driven |
| Defined by Roy Fielding, 2000 | Origin | Simple Object Access Protocol |
Platform Event vs CDC
| Platform Event | Aspect | Change Data Capture |
|---|---|---|
| Custom __e payload you define | Payload | Record deltas + changed fields |
| You publish explicitly | Trigger | Automatic on DML |
| 24-72 hours replay | Retention | 3 days replay |
| Custom app-to-app messaging | Use case | Keep external system in sync |
Easy way to remember
R-F-B-R-U-D = Request/reply, Fire&forget, Batch sync, Remote call-in, UI update, Data virtualization
100 callouts, 120s total, 10s default
Named Cred = URL + secret; Remote Site = URL only
100 callouts, 120s total, 10s default
Named Cred = URL + secret; Remote Site = URL only
Interview tips
Q. Why can't a trigger call out directly?
A. Callout would block the transaction; use @future(callout=true) or Queueable with AllowsCallouts.
Q. Enterprise vs Partner WSDL?
A. Enterprise is strongly typed to your org schema; Partner is loosely typed, introspected, multi-org.
Q. Full CRUD on warehouse data, native UI, no storage?
A. Salesforce Connect with writeable external objects via OData or Apex adapter.
Takeaway
Pick the pattern first, then the tech - real time means callout or Connect, decoupled means Platform Events, volume means Bulk API.
💡 Read → Recall out loud → Explain to someone → Answer in the room
3/16
Salesforce Interview Notes · Lead / Architect
★SECURITY & SHARING MODEL★
OWD, sharing, profiles, perm sets, Apex enforcement
๐OWD Baseline
- OWD = most restrictive floor; everything else only OPENS access
- Private / Public Read Only / Public Read-Write
- Public Read/Write/Transfer ⟶ Lead + Case ONLY
- Public Full Access ⟶ Campaigns only
- Controlled by Parent ⟶ detail side of master-detail, NOT editable
- Detail object has no Owner ⟶ no OWD, no sharing rules on it
- 3 columns: internal | external | guest
- External access can NEVER exceed internal access
- Internal Private ⟶ external must be Private too
- Guest users: Read only, free licence, own guest profile
๐๏ธRole Hierarchy
- Shares UPWARD only: manager sees records of users below
- Peers do NOT see each other ⟶ use sharing rules / public groups
- Needs OWD stricter than Public Read/Write + Grant Access Using Hierarchies
- Grant Access Using Hierarchies: locked ON for standard objects
- Can only be unchecked for CUSTOM objects
- Role is OPTIONAL; profile is MANDATORY (exactly one)
- User can change own role; CANNOT change own profile
- Deleting a role ⟶ reassign users first, sharing recalculation runs
๐Sharing Rules
- Owner-based: by owner user / role / role+subordinates / public group
- Criteria-based: by field values, ignores owner
- Only work when OWD = Private or Public Read Only
- Grant ONLY - can never restrict below OWD
- Apply to existing AND new records, automatically
- Access levels: Read Only or Read/Write
- Limit: 300 sharing rules per object = 250 owner + 50 criteria
- Share with: Roles, Roles & Subordinates, Public Groups
- Public Group = "perm set for roles"; group types: Public + Personal
- Delete a group/queue ⟶ references shown, recalculation, access lost
๐คManual + Apex Sharing
- 3 kinds: managed (SF), user managed (manual), Apex managed
- Manual: Sharing button; owner, Full Access user, or admin
- Manual only when OWD more restrictive than Public Read/Write
- Share object: AccountShare, OpportunityShare, MyObj__Share
- __Share auto-created; NOT if OWD = Public Read/Write
- Custom fields: ParentId, UserOrGroupId, AccessLevel, RowCause
- Standard: OpportunityAccessLevel = 'Read'|'Edit'|'All' (never 'Read/Write')
- Custom RowCause (Apex sharing reason) survives owner change
- Custom RowCause maintained only by Modify All Data
- Database.insert(shares, false) ⟶ partial success
๐ชชProfiles & Perm Sets
- Profile = functional access; 1 per user, many users per profile
- Cannot build a profile from scratch ⟶ clone an existing one
- Standard profiles not fully editable / not deletable
- Perm sets ADD only; never restrict. Many per user
- Licence-based perm set ⟶ only users of that licence; "none" ⟶ anyone
- Only Permission Set Group MUTING can remove a permission
- PSG statuses: Updated / Outdated / Updating / Failed
- Permissions are cumulative = union of profile + all perm sets
- Read/Edit profile + Edit/Delete perm set ⟶ Read+Edit+Delete
- Minimum Access - Salesforce = modern recommended baseline profile
๐งฑObject + Field Security
- 4 layers: Org ⟶ Object ⟶ Field ⟶ Record
- Org: login IP ranges, login hours, password policies, MFA
- Object: CRED + View All + Modify All (profile or perm set)
- FLS set on profiles/perm sets; applies to layouts, list views, reports, API
- Admin profile checkbox lets you edit read-only fields
- Transfer Record perm ⟶ change owner with only Read access
- App perm "View and Edit Converted Leads" for converted leads
- Reports/dashboards/documents: access = FOLDER access
- Users are never deleted ⟶ Freeze (keeps licence + records) or Deactivate (releases licence)
- Login IP Ranges set ⟶ "Reset Security Token" option disappears
โ๏ธApex Sharing Keywords
- with sharing ⟶ enforce running user's RECORD-level sharing
- without sharing ⟶ system mode, sees all records
- inherited sharing ⟶ takes caller's mode; defaults to with sharing if entered directly
- inherited sharing = safest for reusable service classes
- Keywords control record level ONLY - not FLS, not object CRUD
- Flow: System Context bypasses OLS/FLS ⟶ run in user context to respect it
- Lightning/Aura: also need Apex Class Access + component visibility filters
๐ก๏ธSOQL Security + Access Check
- WITH SECURITY_ENFORCED ⟶ checks OLS+FLS in SELECT and FROM
- Throws System.QueryException instead of returning data
- WITH USER_MODE + stripInaccessible are the newer alternatives
- Security.stripInaccessible(AccessType.READABLE, recs) ⟶ strips, no throw
- AccessType.CREATABLE ⟶ sanitize before insert; decision.getRecords()
- Describe check: Schema.sObjectType.Contact.fields.Email.isAccessible()
- UserRecordAccess (API v24.0+) ⟶ HasEditAccess / HasReadAccess
- UserRecordAccess: max 200 record Ids, must be a LIST not a SET
- Credentials live in Named Credentials, never in Apex
- Auth: SSO via SAML/OAuth 2.0, Social Sign-On, MFA (TOTP/SMS)
⇄ Quick Comparison ⇄
Profile vs Permission Set
| Profile | Feature | Permission Set |
|---|---|---|
| Exactly one, mandatory | Per user | Many, optional |
| Grant AND restrict | Effect | Grant only (add) |
| Clone only, no new | Creation | Create new freely |
| Tied to licence type | Licence | Licence-based or none |
| Baseline access | Purpose | Extra rights on top |
Enforcing FLS in Apex
| WITH SECURITY_ENFORCED | Feature | stripInaccessible() |
|---|---|---|
| Inline in SOQL | Where | Method on result/DML list |
| Throws QueryException | On violation | Silently removes fields |
| SELECT + FROM clauses | Scope | READABLE / CREATABLE / UPDATABLE |
| Read queries | Best for | Sanitising records before DML |
Easy way to remember
OWD is the FLOOR - hierarchy, rules, manual, Apex only build UP
Sharing keywords = records; SECURITY_ENFORCED = objects + fields
300 sharing rules = 250 owner + 50 criteria
Sharing keywords = records; SECURITY_ENFORCED = objects + fields
300 sharing rules = 250 owner + 50 criteria
Interview tips
Q. Can a sharing rule restrict access?
A. No. Sharing only widens access above OWD; nothing lowers the OWD floor.
Q. Which sharing declaration for a reusable service class?
A. inherited sharing - takes caller's mode, defaults to with sharing if entered directly.
Q. Does with sharing enforce FLS?
A. No. Record level only. Use WITH SECURITY_ENFORCED, USER_MODE or stripInaccessible.
Takeaway
OWD sets the floor, everything else opens it up - and Apex sharing keywords protect records, not fields.
💡 Read → Recall out loud → Explain to someone → Answer in the room
4/16
Salesforce Interview Notes · Lead / Architect
★ASYNCHRONOUS APEX★
Future, Queueable, Batch, Scheduled - limits and gotchas
๐งญPick Your Async
- Future ⟶ callout from trigger + fix Mixed DML. Fire-and-forget.
- Queueable ⟶ chaining, complex types, need a job Id.
- Batch ⟶ millions of records, fresh limits per chunk.
- Scheduled ⟶ run any of the above at a set time.
- Rule: >1 batch of records ⟶ Batch; else Queueable.
- Queueable = modern replacement for @future. Default to it.
- All four get higher (often doubled) governor limits.
- All four can be started from a trigger.
- Flow: Request ⟶ Enqueue ⟶ Persistence ⟶ Dequeue.
- Timing never guaranteed: server + queue depth decide.
โญ๏ธ@future
- MUST be static + return void. No return value ever.
- Params: primitives / arrays / collections of primitives only.
- No sObjects: value may go stale + overwrite newer data.
- Workaround: pass List<Id>, re-query inside. Or JSON.serialize wrapper.
- @future(callout=true) or CalloutException. Default is false.
- 50 calls per transaction; 250,000 per 24h (or licences x 200).
- Cannot chain: future ⟶ future = not allowed.
- Cannot be called from Batch start/execute/finish.
- Callable from trigger, Apex class, Schedulable. 1 from Queueable.
- No job Id ⟶ cannot monitor. Query AsyncApexJob by MethodName/JobType.
- Banned in VF constructor, getMethodName(), setMethodName().
- Order not guaranteed; two can run concurrently ⟶ record locking.
- Process Builder? Wrap it in an @InvocableMethod.
๐ฆQueueable
- implements Queueable ⟶ one method: execute(QueueableContext).
- System.enqueueJob() returns AsyncApexJob Id ⟶ monitorable + abortable.
- Accepts non-primitive members: sObjects, custom Apex types.
- 50 enqueueJob per SYNC transaction; only 1 in async context.
- Exceeded ⟶ LimitException "Too many queueable jobs added to the queue".
- Chaining: 1 child per parent. Stack depth 5 in Dev/Trial orgs.
- Callouts ⟶ implements Database.AllowsCallouts.
- Non-callout job CAN chain into an AllowsCallouts job.
- Check Limits.getQueueableJobs() vs getLimitQueueableJobs() before enqueue.
- Need >1 queueable from batch execute? Schedule them instead.
- No chaining inside tests ⟶ guard with Test.isRunningTest().
- Batches processed / total batches always 0.
๐๏ธBatch Apex
- implements Database.Batchable<sObject>. 3 methods, all required.
- start(BatchableContext) ⟶ Database.QueryLocator OR Iterable<sObject>.
- execute(BatchableContext, List<sObject> scope) ⟶ the work.
- finish(BatchableContext) ⟶ email, chain next job.
- start + finish run ONCE. execute runs ceil(records / scope size).
- Default scope 200, max 2,000. Iterable scope = no upper limit.
- QueryLocator = 50M rows (bypasses row limit). Iterable = 50,000.
- Fresh limits per execute: 200 SOQL, 50k rows, 150 DML, 10k DML rows.
- Rename execute ⟶ execute1 and the class will not compile.
- Database.executeBatch(cls, scope) returns Id ⟶ System.abortJob().
- FOR UPDATE banned in QueryLocator - locking is implied.
- Aggregate queries fail (no queryMore) ⟶ Iterable<AggregateResult>.
- External objects ⟶ must use Iterable, not QueryLocator.
- Only one batch start() runs at a time per org.
๐พState + Failure
- Batch is STATELESS by default: fresh object per execute.
- Database.Stateful ⟶ instance member vars survive between chunks.
- Cost: serialize/deserialize state every execute. Tiny scope = pain.
- 1 record fails ⟶ whole 200 fails, but next batch still runs.
- Committed batches are NEVER rolled back by a later failure.
- Database.update(list, false) ⟶ partial commit, only bad row fails.
- Database.RaisesPlatformEvents ⟶ fires BatchApexErrorEvent on error.
- Subscribers handle the event ⟶ retry/log without touching the batch.
- Track results via successRecord/failRecord Sets + email in finish().
โฐScheduled + Cron
- implements Schedulable ⟶ one method: execute(SchedulableContext sc).
- System.schedule('name', cronExp, obj) returns a CronTrigger Id.
- System.scheduleBatch() = schedule a batch with no Schedulable class.
- Cron = 7 fields: sec min hr day_of_month month day_of_week [year].
- Sec/Min 0-59, Hours 0-23, DOM 1-31, Month 1-12, DOW 1-7/SUN-SAT, Year 1970-2099.
- DOM and DOW cannot BOTH be concrete - one must be ?.
- '0 0 0 ?' = daily midnight. '0 10 17 ? * MON-FRI' = 5:10pm weekdays.
- '0 30 0 1 1 ? *' = 00:30 on Jan 1 every year.
- 100 scheduled jobs active; 250,000 scheduled executions / 24h.
- Lightning UI cannot set minutes/seconds - only a cron expression can.
- No SYNC callout from Schedulable.execute(). Delegate to batch/queueable/@future.
- @future CAN be called from a scheduler. Batch too.
๐Flex Queue + Monitor
- 5 batch jobs queued or active concurrently, per org.
- Flex queue holds 100 more in Holding status. 101st ⟶ LimitException.
- Statuses: Holding, Queued, Preparing, Processing, Aborted, Completed, Failed.
- FIFO, but reorder via System.FlexQueue.moveBeforeJob() / moveAfterJob().
- Batch + Queueable ⟶ query AsyncApexJob (Status, NumberOfErrors, JobItemsProcessed, TotalJobItems, ExtendedStatus).
- Scheduled ⟶ query CronTrigger (TimesTriggered, NextFireTime) + CronJobDetail.
- ctx.getTriggerId() gives the running scheduled job's Id.
- UI: Setup ⟶ Monitoring ⟶ Apex Jobs. Flex order: Setup ⟶ Apex Flex Queue.
- Tests: async inside startTest/stopTest runs sync + not counted.
โ ๏ธWho Can Call What
- Batch from another batch: finish() ONLY.
- From start/execute ⟶ System.AsyncException: Database.executeBatch cannot be called...
- Batch from trigger: legal, bad practice - 5-job limit blows up fast.
- Future from batch: NEVER. Enqueue a Queueable from finish() instead.
- Loophole: batch execute ⟶ web service ⟶ that service calls @future.
- Cursors: start = 15 open per user; execute + finish = 5 each.
- Callouts: 100 per transaction; in batch, 100 per execute().
- Mixed DML = setup (User, Group, Queue, PermSet) + non-setup in one txn.
- Fix: push the setup-object DML into a @future method.
⇄ Quick Comparison ⇄
Future vs Queueable
| @future | Aspect | Queueable |
|---|---|---|
| Static void method | Shape | Class, execute(QueueableContext) |
| Primitives only | Params | sObjects + custom types OK |
| None returned | Job Id | AsyncApexJob Id from enqueueJob |
| Impossible | Chaining | 1 child, depth 5 (Dev/Trial) |
| @future(callout=true) | Callouts | implements Database.AllowsCallouts |
| 50 per transaction | Txn limit | 50 sync / 1 async |
| Not monitorable | Monitoring | Setup + SOQL + abortable |
| Mixed DML, legacy | Best for | Everything else |
Hard Limits
| Limit | Applies To | Value |
|---|---|---|
| Async executions / 24h | All async | 250,000 or licences x 200 |
| Concurrent batch jobs | Batch | 5 queued or active |
| Flex queue (Holding) | Batch | 100 |
| Scope size | Batch execute | 200 default, 2,000 max |
| Records returned | QueryLocator vs Iterable | 50,000,000 vs 50,000 |
| Active scheduled jobs | Schedulable | 100 |
| Query cursors | start vs execute/finish | 15 vs 5 |
| Callouts | Per txn / per execute | 100 |
Easy way to remember
FQBS = Fire, Queue, Bulk, Schedule
5 batches, 50 futures, 100 scheduled, 200 scope
50M QueryLocator, 50K Iterable
5 batches, 50 futures, 100 scheduled, 200 scope
50M QueryLocator, 50K Iterable
Interview tips
Q. Can a batch call a future method?
A. No. Use System.enqueueJob() from finish() instead.
Q. Why no sObjects in @future?
A. Record can change before it runs - stale values would overwrite newer data.
Q. Batch or Queueable?
A. More than one batch of records ⟶ Batch. Otherwise Queueable.
Takeaway
Queueable is the default async; Batch only when one transaction's limits truly cannot hold the data.
💡 Read → Recall out loud → Explain to someone → Answer in the room
5/16
Salesforce Interview Notes · Lead / Architect
★APEX CORE, TRIGGERS & GOVERNOR LIMITS★
Context vars, order of execution, limits, bulkification
โกTrigger Context Vars
- Trigger.new ⟶ List of new sObjects; insert/update/undelete only
- Trigger.old ⟶ List of old versions; update/delete only; ALWAYS read-only
- Trigger.newMap / oldMap ⟶ Map<Id, sObject>; oldMap = update+delete only
- Trigger.newMap NULL in before insert ⟶ no Ids yet ⟶ NPE
- Trigger.new editable ONLY in before triggers; read-only in after
- Trigger.new list itself read-only ⟶ can't add/remove, only set fields
- isExecuting, isInsert, isUpdate, isDelete, isUndelete, isBefore, isAfter
- Trigger.size + Trigger.operationType (System.TriggerOperation enum)
- 7 events: before ins/upd/del + after ins/upd/del + after undelete
- NO before undelete event exists
- upsert fires 4 events: before+after insert, before+after update
- merge ⟶ delete events on losers + update events on winner
- Lead convert DOES fire insert triggers on Account/Contact/Opportunity
โฑBefore vs After
- BEFORE ⟶ validate + default fields on SAME record, no extra DML
- BEFORE ⟶ never issue insert/update on Trigger.new ⟶ recursion/error
- AFTER ⟶ record saved (not committed); Id, CreatedDate, LastModifiedDate available
- AFTER ⟶ create/update related + child records, callouts (async), emails
- Need the Id or newMap? ⟶ after insert
- Lookup child cascade delete ⟶ after delete trigger, query by parent Id
- addError() on record or field ⟶ custom trigger error message
๐ขOrder of Execution
- 1. Load record from DB / init from submitted values
- 2. New values overwrite old
- 3. System validation (required, format, length) + layout rules
- 4. BEFORE triggers
- 5. Custom validation + duplicate rules + system validation again
- 6. Save to DB, NOT committed
- 7. AFTER triggers
- 8-9. Assignment rules ⟶ auto-response rules
- 10. Workflow rules; field update ⟶ before/after update triggers refire ONCE
- 11-12. Escalation ⟶ Processes / flows (after-save record-triggered)
- 13-14. Entitlement ⟶ roll-up summary recalc, parent re-saves, then grandparent
- 15. Criteria-based sharing recalculated
- 16. COMMIT all DML
- 17. Post-commit: email send, @future + queueable enqueued
๐ฆLimits & Bulkification
- Limits reset at start of each transaction; multi-tenant fairness
- LimitException is UNCATCHABLE ⟶ try/catch will not save you
- "Too many SOQL queries: 101" ⟶ hard limit, support cannot raise it
- @future daily cap throws System.AsyncException ⟶ also uncatchable
- Limits.getQueries(), Limits.getDMLRows() ⟶ check consumption pre-emptively
- NEVER SOQL or DML inside a for loop ⟶ collect Ids in Set, query once, DML once
- Bulkify helper methods too, not just the trigger
- >50,000 rows ⟶ Batch Apex; QueryLocator returns up to 50 million, scope 200
- SOQL for loop
for (Account a : [SELECT...])chunks 200 ⟶ saves heap, not rows - Move heavy work to Batch / Queueable / @future for higher limits
- No element cap on List/Set/Map ⟶ heap size is the real ceiling
- Test with 200 records, positive AND negative paths
๐Recursion Control
- Static Boolean flag ⟶ simple, but only safe for <200 records
- 200+ records = multiple batches ⟶ flag blocks batches 2..n silently
- PREFERRED: static Set<Id> of processed Ids ⟶ bulk-safe
- Compare oldMap vs new field value ⟶ run only on real change
- Static Map<Id, value> to detect genuine field deltas
- Unchecked recursion ⟶ CPU time-out errors
- Watch Apex + Flow/Process re-triggering each other
๐พDML vs Database Methods
- insert/update/delete/upsert/merge/undelete ⟶ ALL-or-nothing, throws DmlException
- Database.insert(list, false) ⟶ partial success, no exception thrown
- allOrNone defaults to TRUE = same behaviour as plain DML
- Results: SaveResult (insert/update), UpsertResult, MergeResult, DeleteResult, UndeleteResult
- Loop results ⟶ isSuccess(), getId(), getErrors() ⟶ getStatusCode/getMessage/getFields
- merge only on Lead, Contact, Account ⟶ NOT custom objects
- Hard delete ⟶ delete list; then Database.emptyRecycleBin(list)
- Row locking ⟶ SELECT ... FOR UPDATE
- Rollback ⟶ Database.setSavepoint() / rollback
- Mixed DML: setup (User, Group, GroupMember, PermissionSetAssignment, Queue) + non-setup in one txn ⟶ MIXED_DML_OPERATION; split via @future/Queueable, System.runAs in tests
๐ฆCollections & Classes
- List = ordered, indexed, duplicates allowed
- Set = unordered, unique; primitives + sObjects, NOT collections
- Map = key-value; null key allowed; duplicate key OVERWRITES; String keys case-sensitive
- Dedupe ⟶ Set.addAll(list) then new List<>(set); or SOQL GROUP BY
- Collections passed by REFERENCE; primitives passed by VALUE
- static ⟶ initialised once at class load, belongs to class, not in VF view state
- static method cannot use instance vars; instance method can use both
- private < protected < public < global; private is the default
- global needed for @RestResource, webservice, managed-package API; can't be removed once packaged
- virtual class CAN be instantiated, abstract CANNOT; abstract methods need override
- Interface = 100% abstraction; abstract class = 0-100%
- with sharing = enforce user's sharing rules; without sharing = system context
- inherited sharing = take caller's context; safe default for @AuraEnabled/VF
๐ฃGotchas
- NO callouts from a trigger ⟶ use @future(callout=true) or Queueable + Database.AllowsCallouts
- SOSL in triggers IS now allowed
- Return type mandatory on every method (void if none); constructors exempt
- Field default values NOT applied by
new⟶ sObjectType.newSObject(rtId, true) - VF controller constructor cannot do DML or callouts ⟶ move to action method
- "List has no rows for assignment to SObject" ⟶ query returned zero rows
- Custom exception class name must end in 'Exception' and extend Exception
- Long = 64-bit (-2^63..2^63-1); Integer = 32-bit
- @InvocableMethod: public/global + static, ONE per class, ONE List param, no triggers
- Blob.toString() / Blob.valueOf(); System.Label.X; UserInfo.getUserId()
- Safe navigation ?. beats chained null checks
- One trigger per object; zero logic in trigger, all in handler; no hardcoded Ids
⇄ Quick Comparison ⇄
Context Var Availability
| Event | Trigger.new / newMap | Trigger.old / oldMap |
|---|---|---|
| Before Insert | new YES / newMap NO | NO / NO |
| After Insert | YES / YES | NO / NO |
| Before Update | YES / YES | YES / YES |
| After Update | YES / YES | YES / YES |
| Before Delete | NO / NO | YES / YES |
| After Delete | NO / NO | YES / YES |
| After Undelete | YES / YES | NO / NO |
Governor Limits Per Transaction
| Limit | Synchronous | Asynchronous |
|---|---|---|
| SOQL queries | 100 | 200 |
| Rows retrieved by SOQL | 50,000 | 50,000 |
| SOSL queries (2,000 rows each) | 20 | 20 |
| DML statements | 150 | 150 |
| Records processed by DML | 10,000 | 10,000 |
| CPU time | 10,000 ms | 60,000 ms |
| Heap size | 6 MB | 12 MB |
| Callouts | 100 | 100 |
| @future calls | 50 | 50 |
| Queueable jobs enqueued | 50 | 50 |
| Email invocations | 10 | 10 |
| Mobile push calls | 10 | 10 |
Easy way to remember
100 SOQL / 50k rows / 150 DML / 10k rows / 6MB / 10s -- async doubles heap + SOQL, 6x CPU
BEFORE = same record, no Id. AFTER = other records, has Id
newMap is null in before insert
BEFORE = same record, no Id. AFTER = other records, has Id
newMap is null in before insert
Interview tips
Q. Why is Trigger.newMap null in before insert?
A. Records have no Ids until saved; use after insert if you need Ids.
Q. Best way to stop trigger recursion?
A. Static Set<Id> of processed Ids in a helper class -- bulk-safe unlike a static Boolean.
Q. Plain DML vs Database.insert?
A. DML is all-or-nothing and throws DmlException; Database.insert(list,false) allows partial success via SaveResult.
Takeaway
One trigger per object, logic in a handler, collections outside loops -- every governor limit is per transaction and every LimitException is uncatchable.
💡 Read → Recall out loud → Explain to someone → Answer in the room
6/16
Salesforce Interview Notes · Lead / Architect
★SOQL, SOSL & DATA MODEL★
Queries, relationships, indexes and governor limits
๐SOQL Core
- Salesforce Object Query Language ⟶ retrieve records of one sObject + relatives
- Syntax: SELECT f1, f2 FROM Object [WHERE cond]
- No SELECT * ⟶ must list every field
- Returns List<sObject>, single sObject, or Integer (COUNT())
- Static SOQL = inline in [ ] + bind vars :myVar / IN :myIds
- Dynamic SOQL = Database.query('...') built at runtime
- Clauses: WHERE, GROUP BY, HAVING, ORDER BY, LIMIT, OFFSET
- OFFSET 8 ⟶ returns from record 9 onward; max OFFSET 2,000
- ALL ROWS ⟶ includes recycle bin + archived activities
- Semi-join IN (SELECT...) / anti-join NOT IN ⟶ SOQL has no real JOINs
๐SOSL Core
- Salesforce Object Search Language ⟶ full-text search across many objects
- FIND {Acc1} IN ALL FIELDS RETURNING Account(Name), Contact(Name) LIMIT 4
- Apex uses quotes 'map'; SOAP/REST API uses braces {map}
- Scopes: ALL / NAME / EMAIL / PHONE / SIDEBAR FIELDS
- Wildcards: * = many chars, ? = single char; OR combines terms
- Returns List<List<sObject>> in the order objects were listed
- No match ⟶ empty list for that sObject, not null
- Cast out: Account[] a = (List<Account>)searchList[0];
- Allowed in triggers + classes since API v20.0 (Winter '11)
- No DML directly on search results; text must be indexed to be found
๐Relationship Queries
- Child ⟶ Parent = dot notation, custom rel uses __r not __c
- SELECT Name, Account.Industry FROM Contact
- SELECT Position__r.Salary__c FROM Candidate__c
- Parent ⟶ Child = subquery on plural relationship name
- SELECT Id, (SELECT Id FROM Contacts) FROM Account
- Custom child list: (SELECT Id, Name FROM Candidates__r) FROM Position__c
- Limits: 20 parent-to-child rels/query, only 1 level of nesting
- Limits: 35 child-to-parent rels/query, max 5 levels deep
- Contact.Account.Owner.FirstName = legal 3-level traversal
- Subquery children come back as a list on each parent record
๐งฉRelationship Types
- Lookup ⟶ loose child-parent, child keeps own owner + sharing, one-to-many relationship.
- Master-Detail ⟶ Mandatory field, tight; detail inherits master's ownership/sharing
- Many-to-many ⟶ junction object = 2 master-detail fields
- First MD field created = primary relationship (drives layout/ownership)
- Self relationship = lookup to the same object (Account ⟶ Account)
- Hierarchical = special lookup, User object only
- Standard object can NEVER be the detail side; master only
- Reparenting allowed only if "Allow reparenting" ticked on MD field
- Cascade delete: MD always; lookup optional, bypasses validation rules
- Delete Account ⟶ its Contacts go to Recycle Bin too
๐Roll-Up & Convert
- Roll-up summary = aggregate of children onto the parent record
- Master-detail ONLY (plus some standard rels e.g. Account-Opportunity)
- Types: COUNT, SUM, MIN, MAX ⟶ read-only field on master
- Limit 25 roll-ups per object, raisable to 40 by Support
- Formula = within one record; roll-up = across child records
- Lookup ⟶ MD conversion: every child must already have a parent
- MD ⟶ Lookup conversion: delete all roll-up summaries on parent first
โกIndexes & Selectivity
- Indexed by default: Id, Name, OwnerId, CreatedDate, SystemModstamp
- Also indexed: Master-Detail + Lookup FKs, External ID, Unique fields
- Selective = filter under threshold; else full table scan / timeout
- Standard index: <30% of first 1M rows, <15% after, cap 1,000,000
- Custom index: <10% of first 1M rows, <5% after 1M, cap 333,333
- Kills index: leading %wildcard, !=, NOT, OR on unindexed, NULL on some
- Query plan tool in Dev Console ⟶ cost <1.0 means selective
- Skinny tables + custom indexes via Support for Large Data Volumes
- >200k rows ⟶ selectivity is mandatory, not optional
๐งฎAggregates & Counting
- SELECT COUNT() FROM Obj WHERE ... ⟶ server-side, dodges 50k row cap
- Aggregates: COUNT(), COUNT(Id), SUM, AVG, MIN, MAX, COUNT_DISTINCT
- Non-COUNT() aggregates return List<AggregateResult>
- Read via (Decimal)ar.get('expr0') or an alias
- GROUP BY (API 18.0+) ⟶ distinct values, e.g. GROUP BY Designation__c
- Find dupes: GROUP BY Name HAVING COUNT(Id) > 1
- HAVING filters groups; WHERE filters rows before grouping
- GROUP BY ROLLUP / CUBE ⟶ subtotals; max 2,000 groups returned
๐FOR UPDATE & Locks
- [SELECT ... FROM Account FOR UPDATE] ⟶ row lock until transaction ends
- Prevents lost updates in read-modify-write race conditions
- Cannot combine FOR UPDATE with ORDER BY (implicit order by Id)
- Not allowed with aggregate/GROUP BY queries, or in SOSL
- Waiting txn errors after ~10s: UNABLE_TO_LOCK_ROW
- Lock parent before children, in consistent order ⟶ avoids deadlock
- MD child insert/update locks the master record implicitly
๐ฆLimits + External
- SOQL: 100 queries sync / 200 async; 50,000 rows per transaction
- SOSL: 20 queries per transaction; 2,000 records returned
- Batch Apex QueryLocator: 50 million rows; SOQL for-loop chunks of 200
- External ID: Text, Number, Email, Auto Number; max 25 per object
- External ID = indexed + upsert match key + REST /Account/Ext__c/12345
- Unique blocks duplicates only; External ID is NOT automatically unique
- External objects (Salesforce Connect) __x ⟶ data stays in remote system
- Use External Lookup (parent = external) / Indirect Lookup (match on Ext ID)
- External objects: no roll-ups, no triggers, no SOSL, per-query row caps
- WhoId = Contact/Lead (Name); WhatId = Account/Opp/Case (Related To)
⇄ Quick Comparison ⇄
SOQL vs SOSL
| SOQL | Feature | SOSL |
|---|---|---|
| SELECT | Keyword | FIND |
| One object + related | Scope | Many unrelated objects |
| query() call | API call | search() call |
| List / sObject / Integer | Returns | List<List<sObject>> |
| 50,000 rows | Row limit | 2,000 rows |
| 100 sync / 200 async | Query limit | 20 per transaction |
| Yes, DML on results | DML | No DML on results |
| Structured field filters | Best for | Text: name, email, phone |
| WHERE + indexes | Filtering | Search index, wildcards * ? |
Master-Detail vs Lookup
| Master-Detail | Feature | Lookup |
|---|---|---|
| 2 per object | Governor limit | 40 per object |
| Required on detail | Field required | Optional by default |
| Cascade deletes children | Parent deleted | Clears field or blocks delete |
| Inherits master's sharing | Security | Independent owner + sharing |
| Supported | Roll-up summary | Not supported |
| Only if reparenting allowed | Reparent | Always allowed |
| Master only, never detail | Standard object | Either side |
| 2 MD fields = junction | Many-to-many | Not possible |
Easy way to remember
SOQL SELECTs one tree, SOSL FINDs many trees
MD = Mandatory, Deleted, Inherited, Rolled-up
2 MD, 40 lookups, 50k rows, 2k SOSL
MD = Mandatory, Deleted, Inherited, Rolled-up
2 MD, 40 lookups, 50k rows, 2k SOSL
Interview tips
Q. Why does my query time out on 5M rows?
A. Non-selective filter ⟶ full table scan; index the field, check Query Plan.
Q. Can you roll up over a lookup?
A. No. Master-detail only, or use Apex trigger / Declarative Lookup Rollup Summaries.
Q. How do you avoid record lock contention?
A. FOR UPDATE with consistent lock ordering; keep transactions short; batch by parent.
Takeaway
Relationships, not joins - master-detail buys you roll-ups and cascade delete at the cost of the child's independence.
💡 Read → Recall out loud → Explain to someone → Answer in the room
7/16
Salesforce Interview Notes · Lead / Architect
★LWC CHEAT SHEET★
Lifecycle, decorators, wire vs imperative, events, LDS
๐Lifecycle Hooks
- Order: constructor ⟶ connectedCallback ⟶ render ⟶ renderedCallback
- Parent constructor first; child renderedCallback fires BEFORE parent's
- constructor(): first statement must be super(), no params
- constructor(): no this.template (not in DOM), no document.write/open
- connectedCallback(): fires EVERY insert into DOM ⟶ subscribe, init
- renderedCallback(): LWC-only, fires many times ⟶ guard with hasRendered
- disconnectedCallback(): cleanup, unsubscribe, releaseMessageContext
- errorCallback(error, stack): error boundary, catches DESCENDANT errors
- Mutating reactive props in renderedCallback ⟶ infinite render loop
๐ท๏ธDecorators
- import { LightningElement, api, track, wire } from 'lwc'
- @api = public + reactive; parent sets it; exposed to App Builder
- @api props read-only in child ⟶ never mutate, dispatch event instead
- @track: all fields reactive since Spring '20; only for deep object/array mutation
- @wire(adapter, {param: '$prop'}) ⟶ leading $ = reactive, re-fetches
- Wired property: @wire(getContactList) contact; ⟶ {data, error}
- Wired function receives ({error, data}) on every provision
- Getters compute derived values the template can reference
- Scoped: @salesforce/schema, /apex, /label/c.X, /resourceUrl, /user/Id
- @salesforce/client/formFactor ⟶ Large | Medium | Small
โกApex Rules
- Method must be static + public/global + @AuraEnabled
- @AuraEnabled(cacheable=true) ⟶ client cache; NO DML allowed
- import m from '@salesforce/apex/ClassName.methodName'
- Imperative params = ONE object, keys match Apex param names
- Imperative returns a Promise ⟶ .then().catch()
- refreshApex() from '@salesforce/apex' refreshes wired cached data
- Imperative for: DML, multi-record CUD, on-click timing control
๐กComponent Comms
- Parent ⟶ child: public @api properties in the markup
- Parent ⟶ child method: @api method + this.template.querySelector().method()
- Child ⟶ parent: dispatchEvent(new CustomEvent('nextpage', {detail:{}}))
- Event name lowercase, no spaces; parent listens on<eventname>
- detail is ALWAYS an object; read it via event.detail
- bubbles default false, composed default false, cancelable default false
- composed: true required to cross the shadow boundary
- No relation: pubsub singleton - fireEvent/registerListener/unregisterListener
- pubsub = Aura application event; limited to ONE Lightning page
- LMS spans pages, tabs, pop-outs, utility bar, Aura + Visualforce
๐จLMS Wiring
- Metadata type: Lightning Message Channel (.messageChannel-meta.xml)
- lightning/messageService ⟶ publish, subscribe, unsubscribe, MessageContext
- import CH from '@salesforce/messageChannel/MyChannel__c'
- APPLICATION_SCOPE = receive even when not on the active tab
- Aura: <lightning:messageChannel>; Visualforce: $MessageChannel global
- createMessageContext() ⟶ must releaseMessageContext() in disconnectedCallback
๐Shadow DOM
- this.template.querySelector() searches own shadow tree ONLY
- Cannot pierce into a child component's template
- Query only in renderedCallback or later - DOM must exist
- querySelector returns FIRST match; prefer data-* or lwc:ref over classes
- CSS does not leak in or out across the shadow boundary
- Aura CAN contain LWC; LWC CANNOT contain Aura
- VF ⟶ LWC chain = VF > Aura > LWC, Aura app extends ltng:outApp
- Same namespace: LWC and Aura cannot share a component name
๐๏ธLDS + Navigation
- Stack: Browser > LWC > LDS > Server > UI API > Database
- LDS handles FLS, sharing, record cache ⟶ prefer over Apex when it fits
- lightning-record-form: view/edit, component decides field layout
- record-view-form / record-edit-form: you choose + position fields
- Read: getRecord / getRecords; metadata: getObjectInfo / getObjectInfos
- Single DML: createRecord, updateRecord, deleteRecord - separate transactions
- Multiple records CUD ⟶ imperative Apex only
- Spanning (relationship) fields: max 5 levels deep
- NavigationMixin(LightningElement) + this[NavigationMixin.Navigate]({...})
- To VF: type 'standard__webPage', url '/apex/MyVfPage?id='+recordId
๐จErrors + Config
- Normalise with reduceErrors from c/ldsUtils (lwc-recipes)
- Wired property ⟶ getter: get errors(){ reduceErrors(this.x.error) }
- Wired function ⟶ handle the error member each provision
- Imperative ⟶ .catch(error ⟹ this.errors = reduceErrors(error))
- .js-meta.xml: isExposed, apiVersion, targets, targetConfigs, masterLabel
- Every <property> in targetConfig needs a matching @api field
- Targets: lightning__RecordPage|AppPage|HomePage|Tab|FlowScreen|UtilityBar
- Flow output: type="@salesforce/schema/Contact[]" role="outputOnly"
- fetch() allowed, but host must be a CSP Trusted Site
- Jest (sfdx-lwc-jest) in __tests__/; does NOT count to Apex coverage
⇄ Quick Comparison ⇄
LWC vs Aura
| Aura | Feature | LWC |
|---|---|---|
| Proprietary Aura framework, 2014 | Base | Web standards: custom elements, Shadow DOM, ES6 |
| Up to 8 files (cmp, controller, helper, renderer) | Bundle | html + js + js-meta.xml (+ css, svg, tests) |
| <lightning:input>, <c:myComp> colon | Markup | <lightning-input>, <c-my-comp> hyphen |
| <aura:attribute>, {!v.x} / {!c.doIt} | Binding | Direct {propertyName}, no v. |
| aura:if / aura:iteration | Templating | template if:true / for:each + key |
| Component + application events, aura:method | Events | Standard DOM CustomEvent + @api |
| component.get("c.m"), setParams, $A.enqueueAction | Apex | import @salesforce/apex, @wire or Promise |
| init, render, rerender, afterRender, unrender | Lifecycle | constructor, connected, rendered, disconnected, errorCallback |
| Developer Console works | Tooling | VS Code + Salesforce DX only |
| Can contain an LWC | Nesting | Cannot contain Aura |
| Locker, LDS, base components | Shared | Locker, LDS, base components |
Wire vs Imperative
| @wire | Feature | Imperative |
|---|---|---|
| Declarative, on load + param change | Trigger | You control it, e.g. button click |
| Requires cacheable=true | Annotation | @AuraEnabled, cacheable optional |
| Not allowed - cacheable forbids DML | DML | Allowed |
| Cached; refreshApex() to refresh | Caching | No cache, just call again |
| {data, error} provisioned | Result | Promise .then / .catch |
| '$prop' re-runs automatically | Reactivity | Manual re-invoke |
Easy way to remember
Con-Con-Ren-Dis-Err = constructor, connected, rendered, disconnected, errorCallback
Constructed top-down, rendered bottom-up: child renderedCallback beats parent's
bubbles + composed are both FALSE by default
Constructed top-down, rendered bottom-up: child renderedCallback beats parent's
bubbles + composed are both FALSE by default
Interview tips
Q. Why does renderedCallback loop forever?
A. It mutates a reactive property, triggering another render. Guard with a boolean flag.
Q. Wire or imperative for a Save button?
A. Imperative - wire needs cacheable=true, and cacheable Apex cannot do DML.
Q. pubsub vs LMS?
A. pubsub is one Lightning page only; LMS spans pages, tabs, utility bar, Aura and VF.
Takeaway
LWC is the browser doing the work - standards, shadow boundaries, Promises; @wire reads, imperative writes.
💡 Read → Recall out loud → Explain to someone → Answer in the room
8/16
Salesforce Interview Notes · Lead / Architect
★AURA / LIGHTNING★
Bundles, attributes, events, interfaces, LDS, App Builder
๐ฆBundle Files
- 8 resources; only .cmp markup is mandatory
- Component (.cmp) = markup; Controller = client-side event handling
- Helper = shared/reusable logic, called from controller + renderer
- Renderer = override render/rerender/afterRender/unrender
- Style = CSS; Documentation = usage docs
- SVG = icon shown in Lightning App Builder palette
- Design (.design) = which attrs admins can edit in App Builder
- App bundle (.app) only for standalone app or Lightning Out dependency
๐ท๏ธAttributes + Expr
- <aura:attribute name type default description access/>
- ONLY name + type are required
- Types: String Integer Boolean Date Datetime Double Decimal Long
- Also Array List Set Map, sObject, MyObj__c[], Apex class, Object
- v = value provider for attributes ⟶ {!v.attr}; c = controller ⟶ {!c.handleClick}
- JS: component.get("v.x") / component.set("v.x", val)
- Bound {!v.x} = two-way parent<⟶child sync
- Unbound {#v.x} = one-time pass, cheaper, better perf
- $Label: $A.get("$Label.ns.name") or {!$Label.c.name}
- Design attrs = attributes exposed to App Builder / Community Builder
๐ง Controller vs Helper
- Controller: handles markup events ({!c.method}), keep it THIN
- Helper: common logic, no repetition; helper.method(component, event, helper)
- Controller method CANNOT call another controller method
- Helper CAN call another helper via this.methodName()
- Helper callable from controller, renderer, other helpers
- Helper inheritable: <aura:component extends="c:SharingComponent"/>
- Reusability lives in the HELPER, not the controller
โกEvents
- 3 types: Component, Application, System (init, render, aura:doneRendering)
- 4 steps always: create ⟶ register ⟶ fire ⟶ handle
- Component: <aura:event type="COMPONENT"> + <aura:registerEvent>
- Fire: component.getEvent("name").setParams({..}).fire()
- App: <aura:event type="APPLICATION">; fire via $A.get("e.c:MyEvt")
- Read payload in handler: event.getParam("attrName")
- Capture runs FIRST (top⟶bottom), then bubble (bottom⟶top)
- Default phase = application events only, runs from root node
- event.stopPropagation() halts travel; preventDefault() kills default phase
- Prefer component event: localised, more secure, easier to debug
- aura:method = parent calls child directly, no event needed
- Args in aura:method: event.getParam('arguments')
๐Interfaces
- force:appHostable ⟶ use as a custom tab (also mobile nav menu)
- flexipage:availableForAllPageTypes ⟶ all Lightning pages
- flexipage:availableForRecordHome ⟶ record pages only
- force:hasRecordId ⟶ injects recordId attr (record page + App Builder only)
- force:hasSObjectName ⟶ injects sObjectName attr
- lightning:actionOverride ⟶ override standard New/Edit/View
- force:lightningQuickAction ⟶ quick action w/ header+Cancel
- force:lightningQuickActionWithoutHeader ⟶ no header/footer
- forceCommunity:availableForAllPageTypes ⟶ Experience Builder (needs access="global")
- lightning:isUrlAddressable ⟶ /lightning/cmp/c__MyCmp, state ⟶ v.pageReference
๐ฐ๏ธServer Calls
- Apex method must be @AuraEnabled + public/global + static
- 1) var action = component.get("c.method")
- 2) action.setParams({key:val}) -- keys MUST match Apex param names
- 3) action.setCallback(this, fn) 4) $A.enqueueAction(action)
- enqueueAction queues, does not run now ⟶ batched = "boxcarring"
- response.getState() ⟶ SUCCESS | ERROR | INCOMPLETE | NEW
- response.getReturnValue() = deserialized Apex return
- void @AuraEnabled = useless; callback gets null ⟶ return String/Boolean
- @AuraEnabled(cacheable=true) = client cache, read-only method
- Storable action = server response cached on client
๐๏ธLDS + Data
- LDS = CRUD a record with NO Apex; handles FLS + sharing
- Aura: force:recordData; LWC: lightning/ui*Api wires + lightning-record-form
- Shared cached copy ⟶ all components on page see same data, update together
- De-duplicates identical record requests ⟶ fewer server calls
- Current user w/o Apex: recordId={!$SObjectType.CurrentUser.Id}, fields="Profile.Name,Name"
- FLS-safe: lightning:recordForm / recordEditForm / recordViewForm
- Apex runs SYSTEM mode ⟶ WITH SECURITY_ENFORCED / WITH USER_MODE / stripInaccessible
- Cross-component refresh: <aura:handler event="force:refreshView" action="{!c.doInit}"/>
๐งญApp Builder + Nav
- Lightning App Builder page types: App Page, Home Page, Record Page
- Assignment levels: Org default ⟶ App default ⟶ App+RecordType+Profile
- lightning:navigation + PageReference {type, attributes, state}
- Targets: standard__component / recordPage / objectPage / namedPage / webPage / knowledgeArticle / navItemPage / recordRelationshipPage
- navigate(pageRef) vs generateUrl(pageRef, callback)
- Legacy events: force:navigateToURL / ToSObject / ToList / ToObjectHome
- force:showToast types: info, success, error, warning; mode: dismissible/pester/sticky
- lightning:overlayLibrary ⟶ showCustomModal() for modals
- Lightning Out: <apex:includeLightning/> + app extends ltng:outApp + $Lightning.use/createComponent
- ltng:outApp applies SLDS; ltng:outAppUnstyled does not
๐Lifecycle + Perf
- init fires first: <aura:handler name="init" value="{!this}" action="{!c.doInit}"/>
- doInit runs AFTER init, BEFORE render ⟶ like a constructor
- Order: init ⟶ render() ⟶ afterRender(); data change ⟶ rerender(); destroy ⟶ unrender()
- Overriding in an extending cmp? call superRender/superAfterRender/superRerender/superUnrender
- Change handler: <aura:handler name="change" value="{!v.attr}" action="{!c.h}"/>
- Perf: use LDS, unbound {#}, cacheable=true, fewer handlers, SELECT fewer cols + LIMIT
- Combine actions into one composite request; no debug mode in prod
- ui: tags = old; lightning: tags = SLDS-styled, preferred
- Standalone app needs extends="force:slds" else raw unstyled HTML
- No limit on how many components you can nest
⇄ Quick Comparison ⇄
Component vs Application Event
| Component Event | Aspect | Application Event |
|---|---|---|
| type="COMPONENT" | Declaration | type="APPLICATION" |
| Self or ancestor in containment | Who handles | ANY component in the app |
| component.getEvent("name") | Fire syntax | $A.get("e.c:MyEvent") |
| Bubble + Capture | Phases | Bubble + Capture + Default |
| Child ⟶ parent data up | Use case | App-wide, e.g. navigate to record |
| More secure, easy to debug | Trade-off | Publish-subscribe, hard to trace |
| Default choice | Preference | Only when component event won't do |
Aura vs LWC vs Visualforce
| Aura | Aspect | LWC / VF |
|---|---|---|
| Aura cmp can contain LWC | Nesting | LWC cannot contain Aura |
| force:hasRecordId | Record Id | LWC: @api recordId |
| force:recordData | LDS entry | LWC: lightning/uiRecordApi wires |
| CSS cascades from parent | Styling | LWC shadow DOM: SLDS hooks / shared CSS |
| 2015, component, client-side | vs Visualforce | VF 2008, page-centric, server round trips |
Easy way to remember
Bundle = C-C-H-S-D-R-S-D (Cmp Controller Helper Style Doc Renderer SVG Design)
Events: Create-Register-Fire-Handle
Capture falls DOWN first, Bubble rises UP
Events: Create-Register-Fire-Handle
Capture falls DOWN first, Bubble rises UP
Interview tips
Q. Component vs application event?
A. Component = child to ancestor only; application = any cmp, publish-subscribe, 3 phases.
Q. Why a helper, not the controller?
A. Controller methods can't call each other; helpers can via this.method() ⟶ reuse.
Q. Why Lightning Data Service?
A. CRUD without Apex, enforces FLS + sharing, shared cache, de-dupes record requests.
Takeaway
Thin controller, fat helper, component events over application events, and LDS before Apex.
💡 Read → Recall out loud → Explain to someone → Answer in the room
9/16
Salesforce Interview Notes · Lead / Architect
★VISUALFORCE & CLASSIC★
Controllers, view state, lifecycle, AJAX, migration
๐๏ธController Types
- Standard: auto-generated per object ⟶ save edit delete cancel list
- Custom: Apex class, replaces standard logic; NO-ARG constructor only
- Extension: adds to standard/custom without replacing it
- Standard list/set: needs recordSetVar ⟶ list views, filter, pagination
- <apex:page standardController="Contact" extensions="E1, E2">
- standardController + controller on same page = ILLEGAL
- 1 controller max + unlimited extensions
- Extension constructor takes ApexPages.StandardController con
- Duplicate method names ⟶ resolved left⟶right, later extension wins
- ~100 built-in components; custom via <apex:component>
๐พView State
- Holds controller instance variables between requests (postbacks)
- Stored in a HIDDEN FORM FIELD ⟶ only exists inside <apex:form>
- MAX 170 KB ⟶ "Maximum view state size limit exceeded"
- transient keyword = excluded from view state (also excluded: static)
- Fixes: transient, clear unused collections, ONE <apex:form> per page
- Re-query large lists instead of parking them in view state
- Inspect: Dev Mode + "Show View State in Development Mode" ⟶ View State tab
- transient props do NOT round-trip ⟶ set them in the postback method
๐Lifecycle Order
- GET (first load): constructor ⟶ action="{!init}" ⟶ getters ⟶ render HTML
- Constructor of standard ctrl runs BEFORE extension constructors
- POSTBACK: decode view state ⟶ setters ⟶ action method ⟶ getters ⟶ re-render
- Setters ALWAYS execute before any action method
- action attribute on <apex:page> fires on page load only, not on rerender
- Every displayed value needs a getter; {!x} maps to getX()
- 3 method kinds: getter, setter, action (+ navigation via PageReference)
- 3 binding kinds: data {!acct.Name}, action {!save}, component {!$Component.id}
โกAJAX Actions
- reRender="id" = redraw only those components, no full refresh
- <apex:actionRegion> = only components INSIDE are sent + validated
- actionRegion skips validation of required fields outside it
- <apex:actionFunction> = JS-callable function ⟶ Apex action
- <apex:actionSupport event="onclick"> = one specific component only
- <apex:actionPoller interval="15"> = repeat call, seconds, min 5s
- <apex:actionStatus> = spinner; facets name="start" / name="stop"
- actionFunction cannot be nested inside an iteration component
๐Pagination
- ApexPages.StandardSetController; DEFAULT page size 20
- setCon.setPageSize(10) inside the extension constructor
- next() previous() first() last(); getHasNext() / getHasPrevious()
- getRecords() returns the current page; getResultSize() total
- Max 10,000 records in a StandardSetController set
- Extension ctor: public MyExt(ApexPages.StandardSetController c)
- Override a LIST button ⟶ page MUST declare recordSetVar
- setPageNumber(n) to jump; getCompleteResult() false if >10k
๐ท๏ธKey Tags
- <apex:page> obligatory outer tag, only ONE per page
- showHeader="false" sidebar="false" to strip Classic chrome
- pageBlockTable = standard SF styling; dataTable = fully custom format
- Inputs: inputField inputText inputSecret(password) inputTextarea inputFile inputHidden
- outputLink = plain <a>; commandLink = <a> that fires an action
- pageMessage severity: confirm|info|warning|error; strength 0-3
- selectList/selectRadio/selectCheckboxes fed by selectOption(s)
- <apex:inlineEditSupport>, <apex:include pageName>, <flow:interview name>
- Component doing DML needs <apex:component allowDML="true">
- Current record: ApexPages.currentPage().getParameters().get('id')
๐ขVF Limits
- View state 170 KB | PDF renderAs max 15 MB
- Static resource 5 MB each, 250 MB per org
- Page/HTTP response size max 15 MB
- Max 10 field dependencies per VF page
- Iteration components: 1,000 items (10,000 if readOnly page)
- readOnly mode: 1,000,000 SOQL rows instead of 50,000
- panelBar up to 1,000 items; JS remoting timeout 30,000 ms default
- Remoting config: buffer=true, escape=true, timeout=30000
- Excel: contentType="application/vnd.ms-excel#Contacts.xls"
๐To Lightning
- Tick "Available for Lightning Experience / mobile" on the page
- window.location + sforce.one differ ⟶ use lightning/navigation or sforce.one
- Style with <apex:slds/> instead of pageBlock Classic markup
- Lightning Out: includeScript /lightning/lightning.out.js + $Lightning.use
- Out app must be <aura:application extends="ltng:outApp"> + aura:dependency
- VF inside LEX runs in an IFRAME (visual.force.com) ⟶ cross-domain limits
- Migrate: VF page ⟶ LWC; controller ⟶ @AuraEnabled(cacheable=true)
- No view state in LWC ⟶ state lives client-side, so re-think chunky controllers
- S-Controls (client-side JS widgets) were superseded by Visualforce
⇄ Quick Comparison ⇄
actionFunction vs Remoting
| apex:actionFunction | Aspect | JS Remoting @RemoteAction |
|---|---|---|
| Full postback, view state sent | Payload | Lightweight JSON, NO view state |
| Must sit inside <apex:form> | Form | No form required |
| Synchronous-feeling, slower | Speed | Faster, truly async |
| Instance methods | Method type | static + @RemoteAction required |
| reRender rebuilds markup | UI update | Callback JS updates the DOM |
| Controller state preserved | State | Stateless, no view state access |
Controller Choice
| Standard | Need | Custom / Extension |
|---|---|---|
| Auto CRUD, sharing enforced | Behaviour | Custom logic; extension keeps standard actions |
| No Apex, no tests needed | Effort | Apex class + 75% coverage |
| Runs in user mode | Security | Custom runs SYSTEM mode unless "with sharing" |
| recordSetVar for lists | Lists | StandardSetController in extension |
Easy way to remember
View State = 170 KB in a hidden field, so it needs a FORM
Load: constructor ⟶ action ⟶ getters; Postback: setters ⟶ action ⟶ getters
setRedirect(true) = new request, state LOST; false = same request, state KEPT
Load: constructor ⟶ action ⟶ getters; Postback: setters ⟶ action ⟶ getters
setRedirect(true) = new request, state LOST; false = same request, state KEPT
Interview tips
Q. Why is my page throwing view state errors?
A. Instance vars over 170 KB - mark transient, drop collections, keep one apex:form.
Q. actionFunction or JS Remoting?
A. Remoting for speed/stateless JSON; actionFunction when you need view state and reRender.
Q. Standard controller vs extension?
A. Extension keeps standard save/edit/delete and layers custom logic; custom controller replaces it entirely.
Takeaway
Visualforce is stateful and server-rendered - the 170 KB view state and its postback lifecycle explain nearly every VF bug and every reason to migrate to LWC.
💡 Read → Recall out loud → Explain to someone → Answer in the room
10/16
Salesforce Interview Notes · Lead / Architect
★ADMIN, CONFIG & AUTOMATION★
Flows, declarative tools, layouts, reports, data tools
๐Flow Types & Anatomy
- Screen Flow ⟶ UI screens; Lightning page, quick action, button, Experience Cloud, URL
- Record-Triggered ⟶ create / update / delete; before-save or after-save
- Schedule-Triggered ⟶ start date+time; once, daily or weekly + entry conditions
- Platform Event-Triggered ⟶ fires when an event message is received
- Autolaunched (no trigger) ⟶ called from Apex, REST API, process, or as subflow
- Built in Flow Builder (ex Visual Workflow / Cloud Flow Designer)
- 3 parts: Elements + Resources + Connectors (incl. fault connectors)
- Subflow: only Screen + Autolaunched; screen flow may call either, autolaunched cannot hold screens
- Apex Action = @InvocableMethod; Local Action = client-side Lightning component
- Pass record: Text var named recordId, "Available for input"; or Record-type var for whole sObject
- Fast Lookup / Fast Create = bulk sObject-collection elements
- Distribute + grant "Run Flows" perm or flow access on profile/permission set
โกBefore vs After Save
- BEFORE save ⟶ set fields on the TRIGGERING record, no extra DML, ~10x faster than Process Builder
- BEFORE save runs before before-triggers; AFTER save runs after after-triggers, with processes
- AFTER save ⟶ related records, email alerts, Chatter, custom notification, Apex, submit for approval
- Entry condition "Only when a record is updated to meet the condition requirements" ⟶ anti-recursion
- $Record vs $Record__Prior to detect a genuine field change
- One flow per object per timing; set Trigger Order for predictable sequence
- Scheduled Paths (after-save only) for time-delayed work ⟶ never loop or poll
- Async path for callouts / non-transactional work
- Flows share the transaction with triggers ⟶ same SOQL, DML, CPU limits
๐ Flow Design & Gotchas
- 200 records = ONE bulk interview batch; only elements OUTSIDE loops get batched
- NEVER Get / Create / Update / Delete / Apex / email inside a Loop
- Inside loop use Assignment only ⟶ build collection ⟶ single DML after the loop
- Fault path on every Get, DML, Apex, callout, email, approval element
- Screen fault ⟶ error screen with {!$Flow.FaultMessage}; background ⟶ log to custom object
- Monitor Setup > Paused and Failed Flow Interviews
- Get Records: only the fields you use, tight filter, "Only the first record" when one is enough
- Loop cap ~2,000 iterations per interview; shares 100 SOQL / 150 DML / 10,000 ms CPU
- Debug with a real record + "Debug in rollback mode"; bulk-test 200 rows via Data Loader
- Every edit creates a new VERSION; only one active version; revert supported
- Record Choice Set (queries at runtime) vs Collection Choice Set (reuse a Get) = more efficient
- Screen "Validate Input": formula must be TRUE for VALID ⟶ inverse of validation rules
- No true unit-test framework; XML merge pain in version control
๐งญTool Choice & Migration
- Workflow: only 4 actions - field update, email alert, task, outbound message
- WF field update ⟶ same record or MASTER-DETAIL parent only; never through a lookup
- WF limits: 500 rules per object, 50 active; fires on insert + update only
- Eval criteria: created / created+every edit / created+edited to subsequently meet
- Time-dependent action NOT allowed with "created, and every time it's edited"
- Pending time actions: Setup > Monitoring > Time-Based Workflow
- All matching WF rules fire in one transaction, ORDER NOT GUARANTEED ⟶ updates overwrite
- "Re-evaluate Workflow Rules After Field Change" ⟶ re-runs all rules AND re-fires triggers
- Process Builder: multi criteria nodes, related records, Apex, approvals; no delete, no UI, after-save only
- WF + Process Builder are RETIRED ⟶ all new automation in Flow; use Migrate to Flow tool
- Choose Apex when: complex logic, dynamic SOQL, callouts, huge volume, real error handling
- Trigger beats PB: before-context edits with no extra DML, delete events, bulk-safe
๐งฎFormulas, Roll-ups, Rules
- Formula field: read-only, calculated on view, NOT stored in the database
- Return types: Checkbox, Currency, Date, Date/Time, Number, Percent, Text
- Cross-object formula: up to 10 relationships spanning 5 unique objects, child ⟶ parent
- Cross-object formulas work on lookup AND master-detail
- Roll-up summary: master-detail only, read-only, CANNOT aggregate a cross-object formula
- Workaround: automation copies value into a plain Number field ⟶ roll THAT up
- Roll-up on a lookup ⟶ Apex trigger, Flow, or DLRS / Rollup Helper from AppExchange
- ISBLANK() any type + preferred; ISNULL() legacy, always false on text (text is never null)
- ISPICKVAL(field,'value') to compare picklists; CASESAFEID(Id) turns 15 ⟶ 18 chars
- IMAGE(url, alt) shows an image as a field on the detail page
- Validation rule: formula TRUE = error + save blocked; 100 active per object
- 500 custom fields per object, extendable to 800 via a support case
- 3 ways to make a field required: field definition, page layout, validation rule
- Custom labels: 5,000 per org, 1,000 chars each, $Label / System.Label, translatable
๐งฑLayouts & Record Types
- Page layout = fields, buttons, custom links, related lists, sections; assigned by profile + record type
- Record type = different picklist value sets + layout + business process per profile
- Different picklist values per layout ⟶ use RECORD TYPES, not layouts
- Dynamic Forms = fields/sections placed on the Lightning record page with component visibility rules
- Mini page layout ⟶ hover detail + console tab fields (no related lists in hover)
- Field dependency: controlling field must be a picklist or CHECKBOX; dependent is a picklist
- Global action = create only, no parent link, sits on global publisher layout
- Object-specific action = create + update + log a call + email, auto-related to the record
- 3 custom tab types: custom object, Visualforce, Web tab
- App Launcher visibility = profile tab settings (Default On/Off/Hidden) + assigned apps
- Record Name field data type: Auto Number or Text only
- Skip record type selection page ⟶ personal setting > Record Type Selection
- Email templates: Text, HTML (letterhead), Custom (no letterhead), Visualforce
โ Approvals & Assignment
- Approval process = entry criteria + steps + approvers + submit/approve/reject/recall actions
- Records can be locked while pending approval
- Records still PENDING ⟶ process can only be deactivated, never deleted; approve/reject/recall first
- Email Approval Response: Setup > Process Automation Settings; reply line 1 keyword, line 2 comment
- Keywords: Approve, Approved, Yes // Reject, Rejected, No
- "Dynamic approval" = approver resolved at runtime: Related User lookup or submitter chooses
- Pattern: Flow stamps a custom User lookup pre-submission ⟶ step = Related User > that field
- Queues: Lead, Case, all custom objects (+ Order, Service Contract, Knowledge Article Version)
- Assignment rules: Leads and Cases ONLY - never custom objects
- Many rules per object but only ONE ACTIVE; ordered entries, first match wins
- From Apex set Database.DMLOptions.assignmentRuleHeader explicitly
- Auto-response rules: Web-to-Case / Web-to-Lead, one active per object, first match wins
- Escalation rules: age-based case reassign + notify
- Lead convert ⟶ Account + Contact + optional Opportunity; map custom fields or data is LOST
- Database.LeadConvert + setConvertedStatus + Database.convertLead; merge max 3 leads
๐Reports & Dashboards
- 4 formats: Tabular, Summary, Matrix, Joined
- Tabular = fastest, no grouping; usable on a dashboard ONLY with a row limit set
- Summary = row groupings + subtotals; grouping mandatory before adding a chart
- Matrix = grouped by rows AND columns for two-dimension comparison
- Joined = up to 5 blocks, each block its own report type
- Report type = the template giving a report its structure; standard or custom
- Bucket field exists only inside the report; supports Picklist, Number, Text
- Conditional highlighting: max 3 colours / 2 breakpoints; needs a summary or matrix report
- Dashboard: max 20 components, each backed by ONE source report; folders control access
- Components: bar, line, pie, donut, funnel, scatter, Gauge, Metric, Table, Visualforce page
- Standard dashboard shows the RUNNING USER's data; dynamic shows the logged-in viewer's
- Report exports to Excel/CSV only ⟶ PDF via Printable View or dashboard "Save as PDF"
- Analytic snapshot FAILS if the target object has a trigger or the running user is inactive
๐พData Ops Gotchas
- Mass Delete Records: standard objects, 250 records at a time
- Hard delete needs "Bulk API Hard Delete" perm + Bulk API option ⟶ bypasses Recycle Bin
- Export excludes Recycle Bin; Export All includes it; SELECT * is not supported
- Recycle Bin records AND deleted custom objects restorable for 15 days
- Data Export (Setup > Data Export): CSV backup, weekly/monthly, min 48-hour interval
- Relationships: load parents first; child column header Account:MyExtId__c links by External Id
- Upsert needs an External Id or record Id; plain update matches on SF Id only
- NO rollback in Data Loader ⟶ export a backup first; revert using success-file Ids
- CSV only, UTF-8 encoding; consumes the org's API limits; Bulk API serial mode avoids row locks
- Data loss causes: changing a field's data type, bad imports, integration errors, governor limits
- Setup Audit Trail: last 20 changes on screen, 6 months downloadable as CSV
๐Settings vs Metadata
- Custom Setting types: List (static org-wide) vs Hierarchy (org > profile > user, most specific wins)
- Cached in app cache ⟶ reads cost NO SOQL query; 10 MB org cap
- Usable in formulas, validation rules, workflow, Apex, VF, flows, API ($Setup)
- Records are DATA ⟶ NOT deployable; only the definition deploys
- No page layouts, lookups, long text areas, validation rules or triggers on custom settings
- Classic use: production kill-switch to disable a trigger
- Custom Metadata (__mdt): records are METADATA ⟶ deploy via change sets / packages
- Auto-present in every new or refreshed sandbox; read-only in Apex at runtime
- Supports fields, page layouts, validation rules, metadata relationships, long text areas
- SOQL-queryable but does NOT count against SOQL governor limits
- getValues(id) ⟶ the raw single row exactly as stored ⟶ use when WRITING
- getInstance(id) / getOrgDefaults() ⟶ merged up the hierarchy ⟶ use when READING
- getInstance() no-arg = running user's merged view; always returns a row even if none stored
⇄ Quick Comparison ⇄
Flow Types At A Glance
| Flow Type | Runs When | Use It For |
|---|---|---|
| Screen Flow | User launches it, interactive | Guided input, surveys, wizards |
| Record-Trig (Before Save) | Before record written to DB | Same-record field updates, no extra DML |
| Record-Trig (After Save) | After record saved, not committed | Related records, email, Chatter, Apex |
| Record-Trig (Delete) | Before the delete | Blocking / cleanup on delete |
| Schedule-Triggered | Set time; once / daily / weekly | Batch cleanup, nightly recalcs |
| Platform Event-Trig | On event message received | Integration, decoupled async work |
| Autolaunched (no trigger) | Called by Apex, API, process, parent flow | Reusable background logic, subflows |
Import Wizard vs Data Loader
| Data Import Wizard | Feature | Data Loader |
|---|---|---|
| Under 50,000 records | Volume | 50k up to 5 million |
| Browser-based, inside Setup | Install | Client app, needs Java/JRE + API Enabled |
| Lead, Contact, Account, Campaign Member, Solution + all custom | Objects | All standard + custom (no User in Wizard) |
| Import only | Direction | Import + Export + Export All |
| Cannot save mappings | Mapping | Saves reusable .sdl mapping file |
| Insert, update, upsert | Operations | + delete and hard delete |
| Name, email or SF Id | Match on | SF Id, or External Id for upsert |
| No | CLI / scheduling | Yes - process-conf.xml + cron/Task Scheduler |
Easy way to remember
Before-save = same record, no DML. After-save = everything else
Workflow 4 actions, PB no delete, Flow does all ⟶ both retired
getValues to WRITE, getInstance to READ
Workflow 4 actions, PB no delete, Flow does all ⟶ both retired
getValues to WRITE, getInstance to READ
Interview tips
Q. When do you use a before-save record-triggered flow?
A. Same-record field updates only - no extra DML, roughly 10x faster than Process Builder.
Q. Roll-up summary on a lookup relationship?
A. Not supported - use Apex, Flow, or DLRS/Rollup Helper; master-detail is required for native roll-ups.
Q. Custom Setting or Custom Metadata Type?
A. CMDT when the config must deploy between orgs; Custom Setting when it varies per profile/user.
Takeaway
Build everything in Flow - before-save for the record itself, after-save for the rest - keep queries and DML outside loops, and put fault paths on every element.
💡 Read → Recall out loud → Explain to someone → Answer in the room
11/16
Salesforce Interview Notes · Lead / Architect
★TESTING, DEPLOY & DEVOPS★
Coverage, mocks, sandboxes, change sets, CI/CD
๐งชTest Class Rules
- @isTest on class = test class; @isTest on method = test method
- testMethod keyword = legacy; use @isTest per method
- Test code does NOT count vs org Apex code size limit
- Asserts both positive AND negative: System.assertEquals(expected, actual)
- NEVER hardcode Ids in test or Apex classes
- Bulk test with up to 200 records + real-world scenarios
- @TestVisible ⟶ test can reach private members
- System.runAs(user) ⟶ profile / permission / sharing context
- Test.isRunningTest() ⟶ bypass code that must not run in test
- Test.loadData() ⟶ build records from static resource CSV
- Test.setCurrentPage(pageRef) ⟶ else ApexPages.currentPage() is null
๐Coverage Numbers
- 75% ORG-WIDE Apex coverage required to deploy to production
- Every TRIGGER must have SOME coverage (> 0%)
- "1% per trigger" is a myth; no real per-trigger percentage
- NO per-class minimum ⟶ a class can sit at 0%
- All tests must PASS, not just cover
- Braces, comments, System.debug lines = white, not counted
- Apex cannot be edited in production; Visualforce CAN be
- Apex Hammer = SF runs your tests on current + next release, diffs results
โฑ๏ธstartTest / stopTest
- Test.startTest() ⟶ fresh set of governor limits for code under test
- Test.stopTest() ⟶ forces queued async work to run synchronously
- ONE startTest/stopTest pair per test method
- Tests future, Queueable, Batch, Scheduled ⟶ assert AFTER stopTest()
- Batch: execute() runs ONCE in test ⟶ insert <= 200 records (batch size)
- Create batch data BEFORE Database.executeBatch(), matching start() query
- start() query returns nothing ⟶ execute() never runs ⟶ 0% coverage
- Chained batches: separate test method per batch class
๐๏ธ@TestSetup + Data
- @testSetup method creates data once, reused by all test methods
- ONLY ONE setup method per test class
- Rollback to setup state between test methods
- Custom METADATA records visible in tests; custom SETTINGS must be created
- @isTest(SeeAllData=true) ⟶ sees real org data; AVOID it
- Default = tests see NO org data (isolation)
- SeeAllData only for exceptional objects (e.g. old Pricebook)
- Set read-only CreatedDate via JSON.deserialize(json, Case.class) - in memory only
- Cannot commit an arbitrary CreatedDate to the DB
๐Mocking Callouts
- Real callouts in tests THROW ⟶ must mock
- implements HttpCalloutMock ⟶ HTTPResponse respond(HTTPRequest req)
- Register BEFORE code under test: Test.setMock(HttpCalloutMock.class, new MyMock())
- SOAP stubs ⟶ WebServiceMock + Test.setMock(WebServiceMock.class, ...)
- StaticResourceCalloutMock / MultiStaticResourceCalloutMock = body in static resource
- Many endpoints ⟶ one mock, if/else branch on req endpoint/method/body
- MultiStaticResourceCalloutMock maps endpoint ⟶ static resource
- Callouts block the thread ⟶ use @future(callout=true) or Queueable
- Cover catch block: runAs a user without access, or violate validation/required field
๐๏ธSandboxes
- 4 types: Developer, Developer Pro, Partial Copy, Full
- Copy of production metadata; data depends on type
- Sandbox NAME max 10 characters
- Org ID CHANGES on every sandbox refresh
- Dev/Dev Pro = metadata only, no data
- Partial Copy = sample data, up to 10,000 records per object
- Full = complete copy incl. all data ⟶ use for UAT / perf / training
๐Deployment Paths
- Change Sets: outbound (source) + inbound (target), needs deployment connection
- Related orgs only; METADATA only - records never move (use Data Loader)
- Steps: add components + dependencies ⟶ upload ⟶ validate ⟶ deploy
- Validate with named test classes ⟶ Quick Deploy inside validation window
- Ant / Force.com Migration Tool: Java+ANT, Metadata API, can DELETE metadata
- destructiveChanges.xml = deletions via Metadata API
- SFDX/CLI: sf project deploy start, source-tracked, scratch orgs, CI-friendly
- Packages: managed (locked, upgradable, namespaced) vs unmanaged (editable, no upgrade)
- Unlocked / 2GP packages = modern modular org deployment
- Data Loader CANNOT move metadata; Communities need Network + CustomSite + ExperienceBundle
๐CI/CD + Git
- Salesforce stores no versions ⟶ Git repo lives OUTSIDE the org
- 3 dev models: change set, org development, package development
- Branch per user story ⟶ dev sandbox/scratch org ⟶ integration ⟶ UAT ⟶ prod
- Commands: init, config, clone, checkout, status, add, commit, pull, push, merge
- Tools: Azure DevOps, Copado, Gearset, Jenkins, AutoRABIT, Flosum
- Copado = SF-native DevOps; PMD / SonarQube / CodeScan static analysis
- Copado nouns: Credential, Environment, User Story, Commit, Promotion, Release
- Back promotion = push prod/UAT changes DOWN to lower orgs after hotfix
- Flows: never edit active version ⟶ Save As New Version ⟶ activate; rollback = reactivate
- Flow XML merges badly ⟶ one owner per flow per sprint
⇄ Quick Comparison ⇄
Sandbox Types & Refresh
| Sandbox | Data + Storage | Refresh |
|---|---|---|
| Developer | Metadata only, 200 MB | Daily (1 day) |
| Developer Pro | Metadata only, 1 GB | Daily (1 day) |
| Partial Copy | Sample data, 5 GB, 10k rec/object | Every 5 days |
| Full | Full copy of production data | Every 29 days |
Change Sets vs SFDX
| Change Sets | Feature | SFDX / CLI + Ant |
|---|---|---|
| Point-and-click in org | Interface | CLI + XML manifest |
| Related orgs only | Scope | Any org, any repo |
| No | Version control | Yes, Git-native |
| No (manual re-add) | Deletions | destructiveChanges.xml |
| Manual, not repeatable | CI/CD | Fully automatable |
Easy way to remember
75 / 200 / 1
Seventy-five percent org, 200 records per batch test, ONE @testSetup
Dev daily, Partial 5, Full 29
Seventy-five percent org, 200 records per batch test, ONE @testSetup
Dev daily, Partial 5, Full 29
Interview tips
Q. Minimum coverage to deploy?
A. 75% org-wide, all tests pass, every trigger has some coverage; no per-class minimum.
Q. Why Test.startTest()?
A. Fresh governor limits for code under test + forces async work to finish at stopTest().
Q. How do you test a callout?
A. Implement HttpCalloutMock.respond(), register with Test.setMock() before invoking the code.
Takeaway
75% is a deployment gate, not a quality bar - assert behaviour, mock callouts, and let Git, not the org, hold your versions.
💡 Read → Recall out loud → Explain to someone → Answer in the room
12/16
Salesforce Interview Notes · Lead / Architect
★SCENARIO PLAYBOOK★
Situational design answers for lead-level interviews
๐ฆBatch Volume
- 150 batch jobs at once? ⟶ No. Flex queue caps at 100
- Beyond 100 ⟶ Database.executeBatch throws LimitException, job not queued
- Flex queue jobs sit in Holding status
- Flex queue NOT enabled ⟶ status Queued, only 5 concurrent ⟶ max 5 in one go
- Ordering across batches? ⟶ can't control order
- Fix ⟶ Database.Stateful + class var flag; skip B until A processed
- Then re-run batch to pick up skipped records
- Error on 395th of 1000, size 200 ⟶ batch 1 (1-200) already committed
- Batch 2 (201-400) rolls back whole chunk; earlier chunks NOT rolled back
โกTrigger Patterns
- Need parent Id to create child ⟶ after insert / after update only
- before insert ⟶ no Id yet, relationship fails
- Build List in loop, single DML outside loop ⟶ works for 1 or 200
- One trigger per object; logic in handler class
- Account created ⟶ auto Opportunity: after insert + handler.createOpportunities()
- Closed Won ⟶ Contract: compare Trigger.oldMap to catch the transition only
- Guard: skip if opp.AccountId == null (Contract needs AccountId + Status)
- Without oldMap check ⟶ new Contract on every later edit of won opp
๐Round Robin
- Create queue + add users first, then after insert trigger
- Read members: GroupMember WHERE GroupId IN (Group WHERE Type='Queue')
- Filter Users on IsActive = true
- Simple version ⟶ index = Math.mod(ticketNumber, agentSize)
- OwnerId set after insert ⟶ explicit update ticketList
- Remember pointer across transactions ⟶ hierarchy custom setting
- getOrgDefaults() ⟶ User_Index__c = last assigned index
- Advance index per record, write setting back once ⟶ 1 DML regardless of volume
๐งConfig Gotchas
- Object missing in report builder ⟶ Allow Reports unchecked on custom object
- No List custom setting option ⟶ Setup > Schema Settings > Manage List Custom Settings Type
- User can't create campaigns despite profile ⟶ Marketing User checkbox on user record
- @wire returns nothing ⟶ Apex needs @AuraEnabled(cacheable=true), static, public/global
- Change Field Type button hidden on M-D ⟶ roll-up summary exists on parent
- Also: deleted roll-up still in Recycle Bin ⟶ must erase permanently
- Other blockers ⟶ too many M-D on child, detail records needing optional lookup
๐๏ธData Model
- a2 parent of a1, then a1 parent of a2 ⟶ blocked, circular reference error
- A record can never be its own parent in the hierarchy
- M-D on object that already has records ⟶ not directly
- Steps: create Lookup ⟶ populate parent on EVERY record ⟶ convert Lookup to M-D
- Clone from UI, field has default but not on layout ⟶ new record gets FIELD default
- Source record's value cannot carry forward if field is off the layout
- Time-based WF queued, record edited out of criteria ⟶ action removed, never fires
๐งญDeclarative First
- Days in current stage, no code ⟶ standard Last Stage Change Date + Stage Duration
- Enable via Opportunity Update Reminders / Stage Change Fields
- Alt 1 ⟶ field history tracking + Opportunity Field History report type
- Alt 2 ⟶ Stage_Changed_Date__c set by Flow, formula TODAY() - Stage_Changed_Date__c
- Surface with conditional highlighting or Path key fields ⟶ spot stale deals
- Rule of thumb: config > Flow > Apex; declarative lets ops tune thresholds
๐Flow STAR Story
- Situation ⟶ manual renewal opps for entitlements expiring in 60 days
- Task ⟶ automate chain, no Apex, business owns the rules
- Action ⟶ schedule-triggered flow nightly + Get Records (Account, Contract)
- Decision on contract value ⟶ named AM vs queue
- Assignment builds collections ⟶ all DML OUTSIDE the loop
- Fault paths ⟶ log to Integration_Log__c + email admin
- Screen flow on Opportunity ⟶ rep confirms/declines, posts to Chatter
- Result ⟶ ~10 hrs/week saved, no missed renewals, threshold editable by ops
๐Callouts In Batch
- Callouts from batch ⟶ must implement Database.AllowsCallouts
- Up to 100 callouts each in start, execute, finish
- Two calls per record ⟶ wrap both in one service class, call in sequence from execute
- Keep scope small: Database.executeBatch(new TwoCalloutBatch(), 10)
- Gate 2nd call on first.getStatusCode() == 200
- Test ⟶ Test.setMock(HttpCalloutMock.class, ...) canned response per endpoint
- 2nd call depends on async completion ⟶ chain a Queueable from finish()
⇄ Quick Comparison ⇄
Batch Queue Limits
| Flex Queue ON | Aspect | Flex Queue OFF |
|---|---|---|
| 100 jobs | Max submitted at once | 5 jobs |
| Holding | Status after executeBatch | Queued |
| LimitException at 101 | Overflow behaviour | LimitException past 5 |
| Yes, reorder in queue | Can change order | No |
Trigger Timing Choice
| Before Trigger | Need | After Trigger |
|---|---|---|
| No Id yet | Parent record Id | Id available |
| Set fields on same record | Best for | Create/relate child records |
| Not possible | Change OwnerId post-insert | Yes + explicit update |
| N/A | Detect field transition | Trigger.oldMap compare |
Easy way to remember
Flex 100 Holding, no Flex 5 Queued
Child records need a parent Id ⟶ AFTER trigger, DML outside loop
Blocked button or missing option? Look for a checkbox: Allow Reports, Marketing User, cacheable=true
Child records need a parent Id ⟶ AFTER trigger, DML outside loop
Blocked button or missing option? Look for a checkbox: Allow Reports, Marketing User, cacheable=true
Interview tips
Q. 150 batches in one go?
A. No - Flex queue caps at 100; without Flex only 5 concurrent.
Q. Error on record 395 of 1000, size 200?
A. First chunk stays committed; only chunk 201-400 rolls back.
Q. Why can't I convert master-detail to lookup?
A. A roll-up summary exists on the parent - including one still in the Recycle Bin.
Takeaway
Scenario answers win on the constraint you name - the exact limit, the checkbox, or the after-trigger reason.
💡 Read → Recall out loud → Explain to someone → Answer in the room
13/16
Salesforce Interview Notes · Lead / Architect
★PLATFORM FUNDAMENTALS★
Multitenancy, clouds, objects, licences, releases, integration architecture
๐ขMultitenancy
- One shared infrastructure + ONE code base serves every customer org
- Your org = your tenant; OrgId partitions every row of shared tables
- Metadata-driven runtime: apps are metadata rows, not per-tenant schema
- No servers, no version to install, no upgrade project ⟶ SaaS
- Governor limits exist so one greedy tenant cannot starve the others
- Limits are per-transaction and reset at each new transaction
- Sync: 100 SOQL, 150 DML, 50,000 rows queried, 10,000 rows DML'd
- CPU 10,000 ms sync vs 60,000 ms async; heap 6 MB vs 12 MB
- 100 callouts / txn, 120 s max callout time, 10 s per-callout default
- Async (Batch/Queueable/@future) doubles SOQL to 200 + heap to 12 MB
- Certified managed package gets its own limit pool; cumulative cap ~11x
- Trade-off framing: "limits are the rent you pay for shared infrastructure"
โ๏ธThe Clouds
- Sales Cloud - the selling process: Lead ⟶ Opportunity ⟶ Closed Won
- Service Cloud - post-sale support: Cases, Knowledge, Console, Omni-Channel
- Marketing Cloud - Email Studio, Journey Builder, Automation Studio, Mobile Studio
- Account Engagement (Pardot) = B2B marketing automation, not Marketing Cloud
- Commerce Cloud - B2C/B2B storefront: catalogue, cart, checkout, OMS
- Experience Cloud (ex-Community Cloud) - portals, help centres, partner sites
- CRM Analytics (ex-Einstein/Analytics Cloud) - datasets, lenses, dashboards
- IoT Cloud - device event streams ⟶ orchestration rules ⟶ SF actions
- Heroku - PaaS in Node/Java/Ruby/Python, wired back via Heroku Connect
- Quip - docs, sheets and chat embedded on records
- Industry clouds e.g. Automotive: Dealer Mgmt, digital retailing, connected car
- Einstein = AI layer over CRM data; now Einstein GenAI + Agentforce
๐Sales & Service Flow
- Sales: Campaign ⟶ Lead ⟶ qualify ⟶ Convert ⟶ Account+Contact+Opportunity
- Convert creates 3 records; Opportunity is optional at conversion
- Lead = unqualified, holds person AND company on one unverified record
- Opportunity = the money: Stage, Amount, Close Date, Forecast Category
- Converted Lead detail page is NOT shown ⟶ links to Acct/Con/Opp instead
- Sales objects: Lead, Account, Contact, Opportunity, Quote, Product, Price Book
- Service capture: Web-to-Case, Email-to-Case, phone/CTI, Chat, community
- Service routing: assignment rules ⟶ queues ⟶ Omni-Channel ⟶ escalation
- SLAs via Entitlements + Milestones; auto-response rules, macros, Case Feed
- Resolution aids: Knowledge articles, Case Teams, Case Comments
๐Objects & IDs
- 5 system/audit fields on every object: Id, Name, CreatedBy, LastModifiedBy, Owner
- Also CreatedDate + LastModifiedDate + SystemModstamp (delta-sync key)
- Detail side of master-detail has NO OwnerId - inherits parent's owner
- Id 15-char = case-SENSITIVE (UI/URL); 18-char = checksum, case-insensitive
- Use 18-char in Excel/exports/integrations to avoid case-collision bugs
- First 3 chars = key prefix naming the object: Account = 001, Contact = 003
- Suffixes: __c custom object/field, __e event, __b big object, __mdt custom metadata
- Field types: Text, Number, Picklist, Formula, Roll-Up, Lookup, Master-Detail
- External Id field = upsert match key from an outside system
- App = group of tabs working as a unit; tabs = the menu items of an app
๐Relationships
- Lookup: loose, optional, no cascade delete, child keeps own owner + sharing
- Master-Detail: tight; child inherits owner + sharing, cascade delete, required
- Roll-Up Summary fields only on the MASTER side of master-detail
- Max 2 master-detail + up to 40 relationship fields per object
- Many-to-many = junction object with 2 master-details
- FIRST master-detail on a junction = primary: controls look/feel + detail page
- Reparenting off by default on master-detail; can be enabled per field
- Hierarchical relationship = User object only (e.g. Manager)
- External lookup / indirect lookup join external objects via Salesforce Connect
- Relationship names: child⟶parent Account.Name; parent⟶child Contacts (r for custom)
๐๏ธMVC & Anatomy
- Model = objects, fields, relationships (data layer, held as metadata)
- View = LWC, Aura, Visualforce, Lightning App Builder pages
- Controller = Apex classes/triggers holding the business logic
- Salesforce.com = SaaS CRM apps (Sales/Service) sold prepackaged
- Force.com = the PaaS beneath it; SF's own apps are built on it
- Now branded Salesforce Platform / Lightning Platform
- User = unique username, email, Profile, optional Role, user licence
- Licence sets what you CAN access; Profile + Perm Sets set what you DO
- Chatter = real-time collaboration: feeds, groups, follows, @mentions, files
- Mobile: Salesforce Mobile SDK, hybrid, or React Native
๐ซLicences & Experience
- 5 Experience Cloud licence types for external users
- External Apps (B2C), Customer Community (B2C), Customer Community Plus (B2C+B2B)
- Partner Community (B2B), Channel Accounts (per-account, not per-user)
- Customer Community: no roles, no sharing rules, high-volume portal user
- Customer Community Plus + Partner: roles + sharing rules + reports
- Partner Community = PRM site: leads, deal registration, shared content
- Person Accounts: Customer Community + Customer Community Plus only
- Business Accounts: Customer, Customer Plus and Partner Community
- Build in Setup > Digital Experiences > All Sites > Experience Builder
- Add partner users: Manage Users tab ⟶ invite by email ⟶ grant permissions
- Manage Partners permission = view Consulting Partner status + certifications
๐๏ธReleases & AppExchange
- THREE releases a year: Spring, Summer, Winter - auto-applied, no opt-out
- Named for the upcoming year (Winter '26 ships in 2025)
- Preview/Release-Update sandboxes get the new version early for regression testing
- Release Updates page = breaking changes with an enforcement deadline
- API versions are honoured, so old code keeps running post-upgrade
- AppExchange = marketplace of apps, components, flows, consultants
- Managed package: namespaced, upgradeable, code hidden, ISV security-reviewed
- Unmanaged package: one-off template, editable, NOT upgradeable
- Installed managed code is exempt from the org's Apex character limit
- Install for admins only / all users / specific profiles
๐Integration Architecture
- Architect answers: who talks to whom, sync or async, what if SAP is down
- APIs: REST (light/JSON), SOAP (WSDL contract), Bulk (millions, async)
- Metadata API = config deploy; Tooling API = classes, coverage, logs
- Composite API: many REST calls in ONE transaction via @{refAccount.id}
- GraphQL API: request exactly the fields needed in one query (UI API)
- Patterns: Request-Reply (user waits) vs Fire-and-Forget (no response)
- Event-driven: Platform Events, CDC, Event Bus, Pub/Sub API (gRPC)
- Middleware (MuleSoft/CPI/Boomi) turns point-to-point into one hub
- API-led connectivity: System API ⟶ Process API ⟶ Experience API
- Auth: OAuth 2.0 - JWT Bearer (server-to-server), Client Credentials, Web Server
- Named + External Credentials store endpoint/secrets; mTLS = both sides verify
- SAP down: queue message, retry 5/15/30 min, Dead Letter Queue, alerting
- Delta records only, keyed on LastModifiedDate / SystemModstamp / CDC
- Cut API usage: Composite, Bulk 2.0, events over polling, middleware cache
⇄ Quick Comparison ⇄
Editions Compared
| Professional | Feature | Enterprise / Unlimited |
|---|---|---|
| 50 | Custom objects | EE 200 / UE 2,000 |
| 100 | Custom fields per object | EE 500 / UE 800 |
| Paid add-on | API access | EE 1,000 calls per licence/day |
| Managed packages only | Apex code | Full Apex, triggers, dev sandboxes |
| Limited automation | Record types + workflow | Full record types + Flow suite |
Platform Events vs CDC
| Platform Event | Criterion | Change Data Capture |
|---|---|---|
| Custom, business event | What it models | Record data change |
| Developer publishes (EventBus.publish) | Publishing | Automatic, zero Apex |
| Order Created, Warranty Registered | Examples | Account/Product/Price Updated |
| __e object, custom fields | Definition | Enable per object in Setup |
| Create only | Operations | Create, Update, Delete, Undelete |
Easy way to remember
Clouds = Sales, Service, Marketing, Commerce, Experience
One code base + 3 releases a year ⟶ limits are the rent
001 = Account: first 3 chars of any Id name the object
One code base + 3 releases a year ⟶ limits are the rent
001 = Account: first 3 chars of any Id name the object
Interview tips
Q. Why do governor limits exist?
A. Multitenancy - shared code and infrastructure, so no single tenant can starve the others.
Q. Salesforce.com vs Force.com?
A. Salesforce.com = SaaS CRM apps; Force.com = the PaaS platform they are built on.
Q. 15 vs 18 character record Id?
A. 15 is case-sensitive from the URL; 18 adds a checksum, safe in Excel and integrations.
Takeaway
Everything on this platform is metadata on shared infrastructure - clouds, licences, limits and releases all follow from that one fact.
💡 Read → Recall out loud → Explain to someone → Answer in the room
14/16
Salesforce Interview Notes · Lead / Architect
★HR + BEHAVIOURAL★
Lead/architect stories, STAR frames, closing questions
๐คTELL ME ABOUT YOURSELF
- Structure = Present ⟶ Past ⟶ Future. ~90 seconds. Then stop.
- Present: current role + scope. "SF Tech Lead/Architect, X yrs, N devs."
- Name the clouds you own: Sales, Service, Experience Cloud.
- Past: 2-3 proof points ⟶ big integration, migration led, perf/data-volume fix.
- Every proof point carries a number: time saved, users onboarded, defects down.
- Future: why THIS role is the logical next step ⟶ "own solution design end to end."
- Mirror JD keywords: LWC, Apex, integration patterns, DevOps tooling.
- Professional story only, never personal history.
- Close by inviting them to dig into any project named. (Asked: Accenture)
โญSTAR FRAME
- S = situation (org, scale, constraint). 1 line only.
- T = task (what YOU owned, not the team).
- A = action = 60% of airtime ⟶ design choices + trade-offs.
- R = result with a metric + what you'd do differently.
- Architect twist: always state the alternative you rejected and why.
- Keep each story to 2 minutes; park detail, let them pull.
- Use "I" for your decisions, "we" for delivery. Never only "we".
- Prep 6 stories, reuse them across 20 questions.
๐ฉนWEAKNESS
- Real but non-critical. Never "I have no weaknesses". Never core to the job.
- 4 steps: Name ⟶ Impact you noticed ⟶ Fix you built ⟶ Result.
- Sample: "Took too much on myself instead of delegating - I was faster."
- Impact: "Became a bottleneck as lead; team waited on my reviews."
- Fix: code-review rotation + design-review checklist + pairing juniors.
- Result: review turnaround 2 days ⟶ a few hours; team designs without me.
- Other safe picks: public speaking, over-polishing docs, impatience with slow decisions.
- Always pair the weakness with the corrective action in flight.
๐ชSTRENGTHS
- Pick 2-3 that match the JD; back each with a STAR mini-story + numbers.
- Solution design under constraints: SF⟶SAP order flow, platform events + middleware queue.
- > 200k orders/month inside governor limits, sync failures near zero.
- Leading + mentoring: run design reviews + onboarding; 3 juniors own modules solo.
- Bridging business + technical: requirements ⟶ design the team builds without rework.
- 2-3 evidenced strengths > a long list of adjectives.
โ๏ธCONFLICT + FAILURE
- Conflict = disagree on design, not personality clash. Data ends the argument.
- Frame: position ⟶ shared goal ⟶ evidence (limits, POC, cost) ⟶ decision ⟶ outcome.
- Classic SF conflict: Flow vs Apex, or "just add another trigger" vs handler pattern.
- Never trash a colleague, client or ex-employer. Escalation is a last step, not step one.
- Failure story: own it, no scapegoat. Missed limit, bad estimate, skipped regression.
- Failure must end in a control you added: checklist, test, gate, monitoring.
- Say what it cost, then what has never happened since.
- Red flag answers: "no failures", or a humblebrag failure.
๐งญLEADERSHIP
- Lead stories they probe: mentoring, estimation, pushing back on scope, tech debt.
- Show influence without authority ⟶ convinced stakeholders with a POC, not a title.
- Quantify the team: N devs, M sprints, X stories, Y orgs.
- Deadline pressure: cut scope, not quality gates; phase the release.
- Say no with an option: "not this sprint, but here is the phased path."
- Prep an answer for "biggest architecture decision you regret".
๐ DAILY + CLOUDS
- Daily: stand-up ⟶ pick sprint stories ⟶ build + unit test config/Apex/LWC.
- Then defects/change requests (CDEX/bugs) on current release.
- Peer code reviews + commits to the version-control branch.
- Coordinate with QA and the BA on acceptance criteria. (Asked: GenPact)
- Cloud answer: Sales Cloud ⟶ Leads, Accounts, Contacts, Opportunities.
- + Products, Quotes, Campaigns, forecasting, reports and dashboards. (Cognizant)
- Dev skills: declarative (objects, fields, relationships, security, automation).
- + Apex, SOQL/SOSL, triggers, Visualforce, Aura, LWC, integration/APIs, testing, deployment.
- + basic OOP (class, object, attributes) + layered UI / business logic / data model.
๐๏ธTOUGHEST MODULE
- Go-to story: legacy ⟶ Salesforce data migration. (Asked: Cognizant)
- Challenges: inconsistent source data, match keys, volume, downtime window.
- Match keys ⟶ External ID fields + upsert. De-dup and cleanse at source.
- Volume ⟶ Bulk API + Batch Apex, scope of 200, millions of rows.
- Load order: parent before child; preserve record ownership and relationships.
- Disable automation during load; stay inside governor + API limits.
- Cut-over ⟶ phased, with reconciliation reports on counts afterwards.
- Close with numbers: records migrated, error rate, how issues were logged and fixed.
โASK THEM
- Never say "no questions" ⟶ reads as no interest. Ask about work, team, tech.
- What does the delivery team look like and where do I fit?
- Biggest technical challenges now: data volume, technical debt, integrations?
- Release process + DevOps tooling: change sets, Copado, Azure DevOps, SFDX pipelines?
- Org maturity: greenfield build or long-lived org needing modernisation?
- How is success measured at 90 days and at one year?
- Growth path and certification support?
- Close: restate interest + ask about next steps in the process.
๐ฐMONEY + NOTICE
- Let them name a number first: "what's the band for this role?"
- If pushed, give a researched range, not a point, and anchor on total CTC.
- Justify with scope: architecture ownership, team size, certs, domain.
- Never inflate current salary; offers get verified against payslips.
- Notice period: state it exactly, then the buyout/early-release option.
- Counter-offer question ⟶ say you have decided to move, and why.
- Have a start date ready; vagueness reads as a competing offer.
⇄ Quick Comparison ⇄
WEAK VS STRONG
| Weak answer | Question | Strong answer |
|---|---|---|
| Life story from college | Tell me about yourself | Present-Past-Future, 90s, JD keywords |
| "I'm a perfectionist" | Weakness | Real gap + fix + measured result |
| "We fixed it somehow" | Toughest module | STAR + External IDs, Bulk API, reconciliation |
| "No, all clear" | Any questions? | Tech debt, DevOps tooling, 90-day success |
| "Whatever you offer" | Salary | Researched range + scope justification |
STORY BANK
| Story | Tests | Best used for |
|---|---|---|
| SF⟶SAP platform events | Design under constraints | Strengths, architecture decision |
| Legacy data migration | Scale + governor limits | Toughest module, pressure |
| Review rotation as lead | Delegation | Weakness, leadership |
| Flow vs Apex debate | Influence + evidence | Conflict, disagreement |
| Missed limit in prod | Ownership | Failure, what you changed after |
Easy way to remember
Present - Past - Future in 90 seconds
STAR: Action is 60%, Result has a number
Every weakness ships with its fix
STAR: Action is 60%, Result has a number
Every weakness ships with its fix
Interview tips
Q. Why should we hire you?
A. Match 3 JD needs to 3 evidenced results, then state the gap you close.
Q. Where do you see yourself in 5 years?
A. Owning end-to-end solution design and growing architects - the path this role starts.
Q. Why are you leaving?
A. Forward-looking and neutral: scope and ownership, never money or a bad manager.
Takeaway
Six rehearsed STAR stories with numbers beat any amount of clever improvisation.
💡 Read → Recall out loud → Explain to someone → Answer in the room
15/16
Salesforce Interview Notes · Lead / Architect
★INTEGRATION ARCHITECT CRIB★
Pattern picking, API limits, auth, middleware, idempotency
๐งญPattern Picker
- If SF calls out + needs the answer on screen now ⟶ Request & Reply (sync)
- If SF fires the update and does not wait ⟶ Fire & Forget (Outbound Messaging)
- If the external system creates/updates SF records ⟶ Remote Call-In
- If nightly/hourly sync of changed rows ⟶ Batch Data Synchronization (ETL)
- If screen must refresh with no user action ⟶ UI Update Based on Data Changes
- If request is queued to devices checking in every 30s ⟶ Fire & Forget + UI Update
- If rep must move on and ERP writes Shipping Number back later ⟶ Fire & Forget
- Metadata API deploy tool waits for the result ⟶ Request & Reply
- If source query takes 7-12 seconds ⟶ never block the UI; async + callback
- Sync only when the user genuinely cannot proceed without the reply
๐คPush Out Of SF
- If real-time push, no Apex, guaranteed delivery ⟶ Workflow/Flow Outbound Message
- OM retries up to 24 hours until ACK; carries a session ID for callback
- OM is SOAP-only ⟶ REST/JSON target? send OM to middleware to translate
- If target is offline 3-4 hours at month-end ⟶ OM queue or ESB queue, no lost txns
- If JSON endpoint + real logic ⟶ Apex REST callout, async (@future / Queueable)
- If many/unknown subscribers + custom payload ⟶ Platform Events (pub-sub, 72h replay)
- If "every field change on this object, no code" ⟶ Change Data Capture
- If users must see live record changes ⟶ Streaming API PushTopic (SOQL-based)
- If the event starts outside Salesforce ⟶ Generic Streaming
- If an outside app polls SF every 2 minutes ⟶ replace polling with Streaming subscribe
- Trigger + @future at 300k orders/day ⟶ hits @future daily limit; move to OM/middleware
๐ชBring Data In
- If millions of rows + PII must stay in source ⟶ Salesforce Connect external objects
- Salesforce Connect: SOQL, global search, reports, related lists; OData 4.0 is writable
- External objects: lookup / external lookup / indirect lookup - NEVER master-detail
- If only the 5 latest orders show on Account ⟶ external object, do not replicate
- If sibling Salesforce orgs need the data ⟶ Cross-Org adapter for Salesforce Connect
- If external UI inside SF that must know the user ⟶ Canvas (signed request)
- Canvas: SDK matches SLDS; Lifecycle Handler changes endpoint URL dynamically
- If a simple unauthenticated web app ⟶ Custom Web Tab, zero code
- If org-to-org sharing after a merger ⟶ Salesforce-to-Salesforce
- S2S gotcha: no built-in support for parent-child related objects
- If Postgres/Heroku sync ⟶ Heroku Connect
- If legacy sends SMTP mail ⟶ Email Services + custom InboundEmailHandler
๐ฆVolume + Bulk
- If 10M+ records to migrate ⟶ Data Loader / Bulk API (Import Wizard caps at 50k)
- If 80M record load ⟶ pre-process, deactivate triggers+workflows, test on Full Sandbox
- Bulk API: async, CSV, 10,000 records per batch, monitored via API and Setup UI
- Bulk API = fewer round trips + far fewer API calls than row-by-row SOAP
- Batch too LARGE ⟶ "Max CPU time exceeded"; too SMALL ⟶ long jobs + record locks
- If lock errors on master-detail parents ⟶ Bulk API serial mode, or sort by parent Id
- Data skew (>10,000 children per parent) ⟶ random-looking parent lock failures
- If nightly delta of 500-1500 Accounts ⟶ getUpdated()/getDeleted() or ETL on SystemModstamp
- Never re-extract all 20M opportunities nightly ⟶ pull modified records only
- Migration + ongoing feed ⟶ Bulk API once, then API call-in for incremental
- Bulk API can load multiple attachments from a single ZIP
๐ฆLimits + Errors
- "Login Rate Exceeded" ⟶ cache the session ID; one integration user per system
- Log in only when the session/token expires; not per call, not stored forever
- "Concurrent Request Limit Exceeded" (sync callout >5s) ⟶ Continuation from the controller
- Continuation = async, up to 3 callouts, frees the long-running concurrent slots
- "Max CPU time exceeded" in a trigger ⟶ smaller batch or move logic to Queueable
- API call limit hit ⟶ Bulk API, REST composite/batch, or declarative Outbound Messaging
- Callout after DML ⟶ "uncommitted work pending"; use @future(callout=true) / Queueable
- 5-minute batch job that takes >5 minutes ⟶ silent overlap, records quietly missed
- Apex callouts burn callout limits, NOT the org's API request limit
- WSDL2Apex generates stub code; document-literal only, no RPC-style SOAP
- Apex REST services cannot be built or maintained declaratively; need unit + functional tests
๐Auth + Certs
- If Apex callout needs stored creds ⟶ Named Credential, never custom settings/hardcode
- If backend rights differ per user ⟶ Named Credential with Per-User identity type
- Per-user NC works for Apex callouts + Salesforce Connect OData; NOT outbound messaging
- Managed package secrets ⟶ Named Credentials + Protected Custom Settings
- If native mobile app ⟶ OAuth User-Agent flow (access + refresh token); REST supports OAuth
- If a portal acts for the logged-in employee ⟶ OAuth on behalf of that user, no shared login
- OM callback auth: session ID in the message, Enterprise WSDL login(), or REST login
- If the remote system must trust Salesforce ⟶ CA-signed cert + two-way (mutual) SSL
- On-prem reachability ⟶ DMZ / reverse proxy, whitelist Salesforce IP ranges on firewall
- Prove payload origin ⟶ digitally sign with a private key; Base64 is encoding, not security
- Platform Encryption protects data at rest, never the network hop - TLS does that
- Least privilege: one credential + profile per integration; never a shared Modify All Data admin
- Client-side callouts from a page ⟶ Remote Site Settings + CORS whitelist
๐Middleware / ESB
- "We write custom code anyway, why middleware?" ⟶ error handling, orchestration, logging
- If complex transformation + process automation ⟶ middleware, minimize Apex
- If a system is retired in 3 months ⟶ ESB not point-to-point; least throwaway code
- If serial acquisitions with different ERPs ⟶ ESB abstracts Salesforce from each system
- Nightly batch middleware must offer ETL + message queuing, not just sync calls
- If 3 systems must update as one unit of work with rollback ⟶ message-oriented middleware
- If credentials must not live in Salesforce ⟶ ESB holds them; SF just fires the message
- If analytics needs SF + other sources ⟶ ETL joins them into one dataset first
- If consolidating orgs ⟶ ETL staging tables for cleansing and standardization
- Middleware also de-dupes repeat calls, retries, replays, and logs the payloads
๐Idempotency + Quality
- If inbound creates may repeat ⟶ upsert() on an External ID, never create()
- Second guard: unique message ID, de-duplicated by the middleware
- External ID: indexed + searchable, upsertable, but NOT unique unless you tick Unique
- External ID can be Text, Number, Email or Auto Number - a formula field cannot
- Cannot flag another External ID ⟶ per-object External ID cap or index cap reached
- No natural key? ⟶ hash first+last+street into a text field and mark it External ID
- If loading a large purchased list ⟶ de-duplicate off-platform BEFORE the load
- Ongoing in-org prevention ⟶ Duplicate Management rules + AppExchange data tool
- Integration write refires the rule ⟶ exclude the Integration User in entry criteria
- Duplicate orders from OM ⟶ compare OM delivery status log against ESB logs
- OM retry after an outage ⟶ expect duplicates + out-of-order; make the consumer idempotent
๐งชTest + Environments
- Callout tests: DML OUTSIDE Test.startTest, the callout INSIDE start/stop
- Mock with HttpCalloutMock / WebServiceMock - live callouts are banned in tests
- Customer CSV test data ⟶ load as a Static Resource + Test.loadData()
- If perf + UAT must mirror prod ⟶ Full Sandbox; Partial Copy for integration testing
- UAT in a Developer sandbox ⟶ false confidence on performance and volume
- Prod data into a sandbox ⟶ Full/Partial refresh or Data Loader
- "New release broke old features" ⟶ Regression testing + continuous integration
- "Meets the spec but feels slow" ⟶ Performance testing + UAT
- Data model churn mid-project ⟶ requirements traceability matrix + CI
- Diagnosing an inbound REST call ⟶ Workbench
⇄ Quick Comparison ⇄
Scenario To Mechanism
| If the scenario says | Choose | Because |
|---|---|---|
| Real-time push, zero code, must not lose messages | Outbound Messaging | 24h retry queue + session ID callback |
| Target speaks REST/JSON only | Apex callout, or OM to middleware | OM emits SOAP only |
| Many or unknown subscribers, custom payload | Platform Events | Pub-sub with 72h replay window |
| Every field change on an object, no code | Change Data Capture | Automatic record-change events |
| Screen updates with no user action | Streaming API PushTopic | UI Update Based on Data Changes |
| Event originates outside Salesforce | Generic Streaming | Non-record notifications |
| Millions of rows, PII must stay in source | Salesforce Connect OData | External objects, nothing copied |
| Nightly sync of changed rows only | ETL + Bulk API + getUpdated() | Batch Data Synchronization |
| Page callout takes 7-12 seconds | Continuation | Dodges concurrent long-running limit |
| Three systems, one transaction, rollback | Message-oriented middleware | Orchestration + compensating rollback |
| External UI in SF that knows the user | Canvas signed request | Passes user and org context |
Enterprise vs Partner WSDL
| Enterprise WSDL | Aspect | Partner WSDL |
|---|---|---|
| Strongly typed, org-specific | Shape | Generic sObject, loosely typed |
| Regenerate after every schema change | New object | One stub covers current + future objects |
| No | Runtime field discovery | Yes - inspect field names at runtime |
| Supports WS-Security | Security | REST API is the OAuth-friendly option |
| Single org, stable data model | Best for | ISV / multi-org, dynamic model |
Easy way to remember
Six patterns: Request&Reply, Fire&Forget, Batch Sync, Remote Call-In, UI Update, Data Virtualization
OM = SOAP + 24h retry + session ID
Upsert on External ID = idempotent
OM = SOAP + 24h retry + session ID
Upsert on External ID = idempotent
Interview tips
Q. Outbound Messaging vs Apex callout?
A. OM is declarative SOAP with a 24h retry queue; Apex gives REST plus logic, but you own retries.
Q. Target system goes offline for hours - now what?
A. Queue it - OM retry or an ESB message queue; never a synchronous trigger callout.
Q. How do you stop an integration creating duplicates?
A. Upsert on External ID, unique message ID in middleware, and de-dupe off-platform before load.
Takeaway
Read the cue - who initiates, how fast, how much - then make every integration queued, idempotent, and least-privileged.
💡 Read → Recall out loud → Explain to someone → Answer in the room
16/16
Salesforce Interview Notes · Lead / Architect
★COMPANY-WISE FOCUS★
What each interviewer actually asked - revise by company
๐ ฐ๏ธAccenture
- Callout from Salesforce ⟶ where do credentials live? (Named Credential)
- Future method limits: 50 per transaction, 250,000 / 24h.
- Batch Apex from a trigger - allowed? Callout from a trigger?
- Remove duplicates from a List in Apex (Set / Map).
- Governor limits - name three. SOQL rows per transaction = 50,000.
- Delete lookup child records when parent is deleted.
- External ID vs Unique ID.
- SOQL for unique designations of employees (GROUP BY).
- Aura framework = MVCC / component-based.
- Dynamic approval process; do workflow rules chain each other?
- Lead conversion + assignment rules.
- Test.setCurrentPage() / Test.setPage() in Apex tests.
- Case management. Plus HR: "Tell me about yourself".
โ๏ธCloud 360
- Platform events - when to use them.
- Permission sets: grant perms to one user, one object.
- Record access restriction levels; OWD default levels.
- OWD internal Private ⟶ can external user be Read/Write?
- Two profiles, R/W vs W/D on same object ⟶ most permissive wins.
- Database.AllowsCallouts - where used.
- Schedulable = 1 method (execute). Queueable = 1 method (execute).
- global access modifier; break vs continue in a for loop.
- Find duplicates using an index.
- Component event propagation phases (capture ⟶ bubble).
- Aura navigate-to-URL; redirect from JS controller.
- Child fires event with X ⟶ parent or super parent?
- Expose component to community via interfaces.
- setRedirect(true) vs (false); duplicate method names across extensions.
- Data Loader Export vs Export All. Custom Settings vs Custom Metadata.
- Community deploy needs Site.com / Network + Experience Bundle.
๐งฉCognizant
- Do you HAVE an exception handling framework? Explain yours.
- One-time migration of lakhs of records - approach.
- MuleSoft <⟶ Salesforce integration; MuleSoft vs Heroku.
- High-volume data in an integration - how to handle.
- Trigger best practices + bulkification example + its aim.
- Order of execution on record save - know it cold.
- Aura event life cycle; framework; design attributes; interfaces.
- CI/CD tool used + Git commands used.
- Sales Cloud life cycle + its objects.
- Lead vs Opportunity - why Opportunity?
- HR: most challenging module; which cloud.
๐GenPact
- Platform Events - worked on them? What are they?
- REST APIs; call external web service from Salesforce.
- Authentication handling (OAuth flows, Named Credentials).
- Future from Batch? Future from Future? Both NO.
- How many future methods per class ⟶ 50 per transaction.
- Accounts + related Contacts in Aura via custom code.
- JS controller vs helper in Aura.
- Slow component ⟶ how to improve performance.
- Scenario: notify managers on an Opportunity.
- Record types driving picklist values.
- HR: what do you do on a daily basis?
๐Appcino
- Only 4 Qs - all Aura + Visualforce.
- Component event vs application event.
- View state in Visualforce - what it is.
- Max view state size = 170 KB (else error; use transient).
- Action region - what it does.
- Verdict: VF-heavy shop. Revise view state + rerender.
๐Mahindra & Mahindra
- Give a user permission to access an Aura component.
- Batch vs Future vs Queueable - the classic contrast.
- Queueable example (implements Queueable, execute).
- Governor limit hit ⟶ how do you rectify it?
- SOQL returns more than 50,000 records ⟶ use Batch / query locator.
- Trace where a quick action / section on a Lightning page comes from.
- doInit in Aura (init handler).
- Partner Community - what it is.
- Verdict: short, async + Aura + community basics.
โป๏ธRepeat Offenders
- Q36 callout to external web service ⟶ Accenture AND GenPact.
- Q480 Aura framework ⟶ Accenture AND Cognizant.
- Async limits show up at Accenture, GenPact, Cloud 360, M&M.
- Aura events appear at Appcino, Cloud 360, Cognizant, GenPact.
- Governor limits + 50,000 SOQL rows: Accenture and M&M.
- Every company slipped in 1-3 HR / experience questions.
⇄ Quick Comparison ⇄
Future vs Queueable
| @future | Feature | Queueable |
|---|---|---|
| static void only | Signature | execute(QueueableContext) |
| primitives only | Params | sObjects + Apex types |
| no job Id | Monitoring | returns AsyncApexJob Id |
| cannot chain | Chaining | 1 child per parent |
| 50 per transaction | Limit | 50 sync / 1 async |
Settings vs Metadata
| Custom Settings | Feature | Custom Metadata |
|---|---|---|
| no | Deployable records | yes |
| yes (List/Hierarchy) | Per user/profile | no |
| no limit consumed | SOQL limits | queries do not count |
| runtime config data | Best for | app config shipped with code |
Easy way to remember
Accenture = limits + admin
Cloud 360 = security + Aura
Cognizant = integration + order of execution
Cloud 360 = security + Aura
Cognizant = integration + order of execution
Interview tips
Q. Which company is the async-heavy one?
A. Mahindra and GenPact - batch vs future vs queueable, chaining rules.
Q. Cloud 360's favourite area?
A. Sharing/OWD plus Aura events - know propagation phases and OWD guest access.
Q. One answer that covers three companies?
A. Named Credentials for callouts - Accenture, GenPact and Cognizant all ask it.
Takeaway
Same 20 topics rotate - master async limits, OWD, order of execution and Aura events.
💡 Read → Recall out loud → Explain to someone → Answer in the room
Keywords:
Short Notes Salesforce interview Questions and Answers Summaryarchitect interview answersadmindeveloper interview questions and answers

