cswork / libraryOpen practice workspace

Interview guides · American Equity (AEL)

American Equity (AEL) Software Engineer Interview Guide

American Equity (AEL) Software Engineer interview guide: Salesforce Apex, SOQL, integrations, LDV and behavioral questions with a 7-day plan.

The 60-second brief

American Equity (AEL) works in insurance and annuities. The Software Engineer role that candidates describe is an Application Developer II or Senior Application Developer position on the Salesforce platform, spanning Sales Cloud, Service Cloud and Marketing Cloud, with complex data models, system interfaces and large integrations. Candidates describe involvement across the project lifecycle, from prototyping and research through planning, development and deployment. Day-to-day topics include Apex triggers and asynchronous Apex, Lightning Web Components, SOQL, Apex REST APIs, Platform Events, large data volumes and release practices built on Git. The reported interview questions use annuity policy data as their running example: exposing policy data to an external portal, syncing daily policy updates, and a policy status endpoint for partners.

This guide is for candidates interviewing as an Application Developer II or a Senior Application Developer on Salesforce at American Equity (AEL). It covers the three reported rounds, fifteen reported questions (Salesforce fundamentals, architecture and integration, behavioral) and a plan that turns them into spoken answers. Candidates report a minimum of 1-2 years of application development for the Developer II level and 4 years for the Senior level, so calibrate the depth of your architecture answers to the level you are applying for.

Candidates report three rounds over roughly 3-5 weeks: a Recruiter Call, Technical Screens and Panel Interviews with senior engineers and engineering managers. The reported emphasis is practical Salesforce discussion rather than abstract algorithm puzzles.

Focus areas

  • Salesforce Platform Development
  • Apex (General)
  • Lightning App Development

Overview

The work behind this loop is custom development on one platform with hard per-transaction limits. That is why the reported fundamentals questions keep returning to the same few ideas: bulkified triggers, the order of execution, SOQL versus SOSL, and choosing between Batch Apex, Queueable and Future methods. A good answer names the limit that is at risk (for example the 100 synchronous SOQL queries that cause the familiar 101 error), shows the code pattern that avoids it, and says how you would prove it with a test that loads 200 or more records in one call.

The second theme is data and integration. Reported scenarios include designing a REST API that exposes annuity policy data to an external portal, syncing daily policy updates in volumes of millions of records, securing a connection to a third-party system, and moving data in with Informatica. Prepare these as design conversations. Start by asking about volume, who the callers are, security and what happens on failure. Then cover authentication, versioning, error handling, retries, chunking and reconciliation, and finish with the trade-off you accepted. Candidates also report that the loop is practical rather than puzzle-based, so time spent on abstract algorithm drills pays back less than time spent talking through Apex, SOQL and integration designs aloud.

The third theme is delivery habits and communication. Candidates report Git for source control, with Salesforce DevOps Center, Code Builder and Copado named as helpful experience, and the reported scenarios include standardising deployments for five developers in one org and reviewing a junior developer's code. The behavioral questions centre on the EPIC values (Empowered, Passion, Integrity, Caring): explaining a roadblock to a business stakeholder, adapting to delay, collaborating inclusively, aligning goals to business objectives and improving a pipeline. For a Senior role, expect to lead architecture discussions and describe how you enforce standards; for Developer II, expect the same topics with more weight on correct, bulk-safe code.

The American Equity (AEL) interview process

Candidates describe three stages, from a recruiter conversation through technical screens to panel interviews. Each stage below says what is reported and how to prepare for it; questions are not tied to a specific round.

Recruiter Call

The Recruiter Call is reported as a first conversation about your background, how you line up with the EPIC values and your foundational Salesforce knowledge. Treat it as a short, spoken version of the whole loop: a clear career summary, one example for each EPIC value, and crisp definitions of the basics. The reported fundamentals questions such as SOQL versus SOSL and Role versus Profile are the kind of material to be able to answer in under a minute each. Use the call to confirm which level the role is (Application Developer II or Senior Application Developer) and what the schedule looks like.

What to demonstrate

  • How clearly you summarise your background and your Salesforce experience
  • Fit with the EPIC values as candidates describe them: Empowered, Passion, Integrity, Caring
  • Foundational Salesforce knowledge at definition level

How to prepare

  • Write a two-minute career summary that names the clouds you have worked in and the biggest Apex, LWC or integration piece you built.
  • Prepare one real example for each EPIC value, and keep each to a few sentences with your own action in it.
  • Rehearse short answers on SOQL versus SOSL and Role versus Profile so you can explain each without notes.
  • Know your certification status (Platform Developer 1 or 2) and whether you are targeting the Developer II or Senior level.

Technical Screens

Technical Screens are reported as practical discussions about Salesforce architecture and integration challenges. Candidates say the format is conversational rather than puzzle-based, so the work is explaining real mechanisms aloud: how a trigger behaves on a bulk load, which asynchronous option fits a workload, how a REST endpoint or Platform Event integration is shaped, and how you would query and update large volumes without lock contention. Ask about data volume, security and business requirements before you commit to a design, and finish each answer with the trade-off you chose.

What to demonstrate

  • Working knowledge of Apex triggers, asynchronous Apex, SOQL and governor limits
  • Ability to reason through integration and architecture scenarios on Salesforce
  • Debugging and reading existing code, which candidates list among the tested topics

How to prepare

  • Walk through refactoring a trigger that runs a query per record: collect ids, query once into a map, one DML after the loop.
  • Build a comparison of Batch Apex, Queueable and Future methods covering volume, chaining, callouts and monitoring.
  • Outline a policy-data REST endpoint: authentication, versioning, error codes, pagination and what it exposes.
  • Practise the LDV answer: selective indexed filters, Bulk API, ordering loads by parent to cut lock contention, and batch sizing.

Panel Interviews

Panel Interviews are reported as interactive sessions with senior engineers and engineering managers covering technical skills and problem-solving. Candidates also describe behavioral conversations at the later stages. Expect to move between design reasoning (Flow versus custom Apex, Platform Events, integration security) and delivery topics such as Git branching, merge conflicts, DevOps Center pipelines and code review. Because several people take part, practise answering the same story at two levels: a short version for a manager and a deeper version for an engineer.

What to demonstrate

  • Technical depth and problem-solving in a live discussion with several people
  • Architecture and process thinking, including release pipelines and code review
  • Accountability, adaptability and collaboration as the EPIC values describe them

How to prepare

  • Prepare a worked answer for standardising deployments across five developers in one org, with branching, review gates and release steps.
  • Write a decision guide for Flow versus Apex covering volume, complexity, testing and maintenance.
  • Rehearse your five behavioral stories with a business-impact line at the end of each.
  • If you target the Senior level, prepare an architecture you led across more than one system and how you enforced standards.

Where candidates lose points

Explaining bulkification only in theory, or leaving a query inside a loop in the example

Walk through the concrete pattern: ids into a Set, one SOQL into a Map, a loop that reads the map, one DML at the end. Say how you would test with 200 or more records and name the limit you are protecting.

Treating Flow versus custom Apex as a matter of taste

Give decision criteria: data volume, logic complexity, who maintains it, testability, and how each interacts with triggers in the order of execution. Then say which you would pick for a specific case and what you give up.

Answering the integration security question with just OAuth

Cover the full chain: how the caller authenticates, a least-privilege integration user and permission set, transport encryption, where credentials are stored, input validation, logging, and how you handle replays and retries.

Answering the large-data-volume question with only use Batch Apex

Start with selective, indexed filters and narrow field lists, then the Bulk API, load ordering by parent to reduce lock contention, and batch sizing. Mention how you would monitor failures and reconcile counts.

Telling behavioral stories in the team voice with no personal decision and no business impact

Use STAR with a clear I: the call you made, the options you weighed and the business effect, such as a date kept, a failure rate reduced or a decision unblocked for a stakeholder.

Questions & practice

How do you approach querying and updating Large Data Volumes (LDV) without causing lock contentions or timeout

Medium · Architecture, Integration, and Data

How do you approach querying and updating Large Data Volumes (LDV) without causing lock contentions or timeouts?

Approach

  1. Make queries selective. Filter on indexed fields (Id, Name, OwnerId, CreatedDate, SystemModstamp, RecordTypeId, lookups, External ID and unique fields, or a custom index from Salesforce support) and confirm a Query Plan cost below 1. A standard index is selective under 30% of the first million rows and 15% beyond (max 1M); a custom index under 10% and 5% (max 333,333).
  2. Name the patterns that defeat indexes: negative operators (!=, NOT IN), leading-wildcard LIKE, comparisons with null on custom-indexed fields, and non-deterministic formula fields. Fixes include adding an indexed date range, skinny tables (enabled by support) and archiving cold policies.
  3. Process in chunks. Batch Apex with Database.QueryLocator can iterate up to 50 million records, and I tune the scope size down when each chunk does heavy DML. For external loads I use the Bulk API, and for very large extracts PK chunking or Bulk API 2.0's automatic query chunking.
  4. Prevent lock contention. Writing child records locks their parent (always for master-detail, and in many lookup cases), so parallel batches touching the same Account fail with UNABLE_TO_LOCK_ROW. I sort load files by parent Id, use serial mode in Bulk API 1.0 when needed, and avoid data skew (over about 10,000 children on one parent or 10,000 records owned by one user).
  5. Reduce per-record work during loads. Bulk-safe triggers, a custom-setting bypass for non-essential automation, deferred sharing calculation for large migrations, and SELECT ... FOR UPDATE only where two writers really race.

Follow-up

  • A nightly batch fails intermittently with UNABLE_TO_LOCK_ROW on Account. What do you check first?
  • The Query Plan shows TableScan on your policy query. What do you change?
  • When would you choose the Bulk API over Batch Apex for a daily policy sync?

Find overlapping job attempts and peak concurrency from lease records

Medium · sweep line · intervals · leases

A day of job_run history yields about 50,000,000 attempt records: (job_run_id, job_type, attempt, started_at, finished_at which is NULL when the worker died, lease_expires_at). Leases expire on a clock, so a job that outran its lease ran twice. Produce (a) every job_run_id whose attempts overlapped in wall-clock time and (b) the peak number of simultaneously running attempts per job_type with the minute it occurred. Target O(n log n). State how you treat a NULL finished_at and what clock skew does to your answer.

Approach

  1. Define the interval before sorting anything: an attempt occupies [started_at, COALESCE(finished_at, lease_expires_at)). finished_at is observed and lease_expires_at is only a promise, so every attempt without a finish contributes an estimate and the whole result is a lower bound on overlap rather than an exact count.
  2. For peak concurrency, sweep: emit 2n endpoints, sort by (timestamp, kind) with ends ordered before starts at equal timestamps, then walk the sequence maintaining a counter per job_type and record each type's maximum with its timestamp. O(n log n) dominated by the sort, O(n) space, or O(1) extra if the sort is external and the walk streams.
  3. For overlap detection, do not compare attempts pairwise. A single global sort by (job_run_id, started_at) gives both the grouping and the order; within a group, keep the maximum end seen so far and report an overlap exactly when the next start is less than that running maximum, which is one linear pass after the sort.
  4. Half-open intervals matter and are easy to get wrong: with closed intervals an attempt ending at the same millisecond another begins reads as concurrency two, and across 50,000,000 records that artefact swamps the real signal.

Follow-up

  • A handler is not idempotent and you have found 400 overlapping jobs. Which of them actually caused damage, and what would you query to find out?
  • Peak concurrency for one job_type is 4 against a configured cap of 4. Is the cap working, or is the data hiding attempts that never started?

Canonicalise a request body into a stable idempotency fingerprint

Medium · parsing · canonicalisation · hashing

idempotency_key.request_fingerprint is a SHA-256 over the method, path and canonicalised body, and a retry whose fingerprint differs must be rejected with 422 rather than served the stored response. Write the canonicaliser. Bodies are JSON up to 256 KB nested at most 32 levels; clients vary key order, whitespace and unicode escaping, and some send 64-bit ids as JSON numbers. Produce a deterministic byte string such that semantically identical bodies match and any semantic difference does not. State your complexity and name two normalisations you refuse to perform.

Approach

  1. Parse once into a tree, then re-serialise under fixed rules: object keys sorted, array order preserved, one escaping convention, no insignificant whitespace. Parsing is O(n) and sorting keys is O(k log k) per object, so O(n log n) overall with O(depth) stack, and the 32-level cap is enforced during parsing because hostile nesting is how a canonicaliser becomes a stack overflow.
  2. Sort keys by their UTF-8 bytes and say why the obvious implementation is wrong in some runtimes: a default string comparison that orders by UTF-16 code units places surrogate pairs, meaning code points from U+10000 up, below U+E000 to U+FFFF, which is not UTF-8 byte order, so two services written in different languages disagree on the same document.
  3. Do not re-encode numbers through a double. IEEE-754 binary64 represents integers exactly only up to 2^53, so normalising a 19-digit id through a float changes it, and 1 against 1.0 cannot be reconciled without deciding whether they are the same value. Preserve the literal token, and require ids as strings at the API boundary if you want them comparable.
  4. Reject duplicate keys rather than picking one. JSON permits them and parsers disagree, most keeping the last, so any choice you make ties the fingerprint to a parser detail that the code handling the request does not necessarily share.

Follow-up

  • A client sends the same logical request with an extra field your API ignores. Same key, different fingerprint, so you return 422. Is that the right answer?
  • Where does the fingerprint get computed relative to request decompression and the body-size limit?

Denormalise tenant onto revisions and backfill it live

Hard · denormalisation · online migration · backfill

resource_revision (revision_id, resource_id, version, actor_user_id, change_kind, patch, request_id, created_at) has 400M rows and no tenant column; tenant_id lives only on resource. Two reads need it: a tenant-scoped audit feed ordered by created_at DESC, and an offboarding purge. Both join back to resource today. Justify adding tenant_id to resource_revision against those two reads, name the anomaly the copy introduces and the constraint that prevents it, then give the ordered migration for a live table taking 1.2k writes/second — the lock each step takes, how the backfill is batched, and where each step stops being reversible. PostgreSQL 16.

Approach

  1. Justify from the access path rather than from taste. Without the column, the audit feed either scans resource_revision by created_at and discards other tenants' rows, or resolves the tenant's resource_ids first and probes with them — both proportional to the tenant's whole history rather than to one page. With (tenant_id, created_at DESC, revision_id DESC) it is a seek that stops at 50 rows, and the purge becomes a ranged delete instead of a join.
  2. Name the cost exactly: a second copy of a fact can disagree with the first. Make the disagreement unwritable rather than documented — add UNIQUE (resource_id, tenant_id) on resource so it can serve as a foreign-key target, then FOREIGN KEY (resource_id, tenant_id) REFERENCES resource (resource_id, tenant_id) on the revision table. A revision can then only ever carry its parent's tenant.
  3. Step one, expand: ALTER TABLE resource_revision ADD COLUMN tenant_id BIGINT NULL, with no default, so it is a catalogue change and no rewrite. It still needs ACCESS EXCLUSIVE for an instant, and that instant queues behind the longest open transaction on the table while every later query queues behind it — set lock_timeout to 2s and retry rather than wait.
  4. Step two, dual-write: deploy the writer that populates tenant_id on every new revision while reads still use the join. Reversible by redeploying the previous build, because nothing reads the column yet.

Follow-up

  • The backfill is half finished and a rollback is required. What state is the table in, and what does the previous build do with a half-populated column?
  • How do you verify the backfill actually finished, given rows are still being inserted while it runs?

Find version gaps and relay lag with window functions

Medium · window functions · event tables · frame semantics

outbox_event holds event_id, aggregate_type, aggregate_id, aggregate_version, event_type, payload, status ('pending','published','dead'), attempts, created_at, published_at. A projection is missing rows and you must decide whether the relay skipped events or the consumer dropped them. Write three queries over the last seven days: one listing every aggregate_id whose published aggregate_version sequence has a hole, one giving per-day counts with a running total, and one returning the newest published event per aggregate. For each, say where the window function is evaluated relative to WHERE and LIMIT. PostgreSQL 16.

Approach

  1. Gaps: compute lead(aggregate_version) OVER (PARTITION BY aggregate_id ORDER BY aggregate_version) in a subquery, then filter next_version <> aggregate_version + 1 in the outer query. Window functions are evaluated after WHERE, GROUP BY and HAVING and before the outer ORDER BY and LIMIT, so the predicate cannot sit in the same WHERE clause and PostgreSQL 16 has no QUALIFY.
  2. Say what the seven-day filter does to the answer: it truncates every partition, so the first row per aggregate has no predecessor inside the window and a hole spanning the boundary is invisible. Widen the window, or join to resource.version as the authority for the true maximum.
  3. Running total: SELECT date_trunc('day', created_at) AS d, count() AS n, sum(count()) OVER (ORDER BY date_trunc('day', created_at) ROWS UNBOUNDED PRECEDING). An aggregate inside a window call is legal because grouping runs before windowing. The grouping key is unique per row here so ROWS and RANGE agree, but write the frame anyway — over ungrouped rows with tied timestamps the default RANGE frame pulls in every peer row and the total jumps.
  4. Newest per aggregate: DISTINCT ON (aggregate_id) ... ORDER BY aggregate_id, aggregate_version DESC is the cheap PostgreSQL-only form when an index matches that order; row_number() OVER (PARTITION BY aggregate_id ORDER BY aggregate_version DESC) = 1 is the portable form and needs a subquery for the same evaluation-order reason as the gap query.

Follow-up

  • Relay failover redelivers events. Does a duplicate break the gap query, and how would you detect one from this table alone?
  • Turn the gap check into a continuous monitor rather than a query someone runs after an incident. What does it watch?

What are the differences between SOQL and SOSL, and when would you use each?

Medium · Salesforce Technical Fundamentals

Approach

  1. Start with the core split. SOQL queries known objects and fields and returns a List<sObject>. It supports WHERE, ORDER BY, GROUP BY, aggregates and relationship queries: dot notation for child-to-parent fields and subqueries for parent-to-child records. SOSL (FIND ... IN ALL FIELDS RETURNING Account(Name), Contact(Email)) searches text across several objects at once and returns a List<List<sObject>>.
  2. Give the decision rule. Use SOQL when you know which object holds the data and you filter on exact values such as an Id, a policy number or a status. Use SOSL for a global search box where the user types a name or email and it could match several objects.
  3. Quote the per-transaction limits: 100 SOQL queries and 50,000 retrieved rows in synchronous Apex, against 20 SOSL searches with up to 2,000 records returned per search.
  4. Explain that SOSL reads the search index, which updates asynchronously, so a record inserted moments ago may not be found yet. In tests, Test.setFixedSearchResults is required because SOSL returns nothing there by default.
  5. Cover safety and performance. Bind variables (:policyNumber) or String.escapeSingleQuotes on dynamic queries prevent SOQL injection. A LIKE '%term' filter cannot use an index, which is often the real reason to switch to SOSL for text search.

Follow-up

  • Why might a record created a few seconds ago not show up in a SOSL search?
  • How would you fetch a policy, its owner's name and all its beneficiaries in a single SOQL statement?
  • What makes a SOQL WHERE clause selective on an object with millions of rows?

Explain the Salesforce order of execution and why it matters when writing Apex triggers.

Medium · Salesforce Technical Fundamentals

Approach

  1. Walk the save sequence in order: system validation, before-save flows, before triggers, custom validation rules, duplicate rules, save without commit, after triggers, assignment, auto-response and workflow rules, escalation rules, after-save flows, roll-up summaries, sharing recalculation, commit, then post-commit work such as email and async Apex.
  2. Draw the consequence for before vs after triggers. Field changes on Trigger.new in a before trigger are free (no DML) and validation rules still check them. In an after trigger the record has an Id but Trigger.new is read-only, so changing the same record needs another DML that runs the save sequence again.
  3. Point out the re-entry cases. A workflow field update fires before-update and after-update triggers one more time. A roll-up summary runs the parent record through its own save, so parent triggers fire in the same transaction and draw on the same governor limits.
  4. Because the order of multiple triggers on one object is not guaranteed, I keep one trigger per object that delegates to a handler class. I guard recursion with a static Set<Id> of processed records rather than a static Boolean, because a bulk save is chunked into batches of 200 and a Boolean flag would skip every chunk after the first.
  5. Mention that future and queueable jobs only start after the commit, so they never see uncommitted data and do not run at all if the transaction rolls back.

Follow-up

  • A workflow field update makes your trigger run twice. How do you keep it idempotent?
  • Where does a before-save flow sit relative to a before trigger, and which one wins if both set the same field?
  • Why can't you set a field on Trigger.new in an after-insert trigger?

Can you explain the difference between a Role and a Profile in Salesforce data security?

Medium · Salesforce Technical Fundamentals

Approach

  1. Profile controls what a user can do: object CRUD, field-level security, app and tab visibility, system permissions, page layouts, record types, and login hours or IP ranges. Every user has exactly one profile, and permission sets or permission set groups add permissions on top of it.
  2. Role controls which records a user can see through the role hierarchy. Users higher in the hierarchy get access to records owned by or shared with users below them. That is always the case for standard objects and the default for custom objects (Grant Access Using Hierarchies). A user has at most one role.
  3. Place both in the record-access layers. Org-wide defaults set the most restrictive baseline, then the role hierarchy, sharing rules (owner- or criteria-based), teams, manual sharing and Apex managed sharing open access further. Profile permissions are a separate gate: a user who can see a record still cannot see a field that FLS hides.
  4. Give an example in the role's domain. Policy OWD is Private, so an agent sees their own policies through ownership and their manager sees the team's through the hierarchy. A criteria-based sharing rule gives a service group read access to one policy type, and permission sets grant edit rights instead of cloning profiles.
  5. Cover Apex. 'with sharing' enforces record-level sharing only, not CRUD or FLS. For those I use WITH USER_MODE in queries, Security.stripInaccessible, or explicit describe checks.

Follow-up

  • A user can open a policy record but a field on it is blank for them and populated for others. Where do you look?
  • How would you give one team read access to a subset of records without changing the role hierarchy?
  • Does a class declared 'with sharing' respect field-level security? What would you add?

What are Platform Events, and how do they differ from Outbound Messages?

Medium · Salesforce Technical Fundamentals

Approach

  1. Define Platform Events. They are a publish/subscribe message bus built on custom event objects (__e). Apex (EventBus.publish), Flow or the APIs can publish, and Apex triggers, flows, LWC (empApi) and external clients over the Pub/Sub API or CometD can subscribe. Publishers and subscribers do not know about each other.
  2. Define Outbound Messages. A declarative action, historically tied to workflow rules, sends a SOAP XML message with selected fields of one object to a single fixed endpoint. The listener must return an acknowledgement. Unacknowledged messages are retried with increasing intervals for up to 24 hours, so the same message can arrive more than once.
  3. Contrast the delivery models. Outbound Messages push point-to-point and need an endpoint Salesforce can reach. Platform Events let many consumers subscribe, and an external subscriber can pull over the Pub/Sub API without opening an inbound port. Stored high-volume events can be replayed by ReplayId inside the retention window (72 hours).
  4. Explain the platform event settings that matter. Publish After Commit means a rollback cancels the event, while Publish Immediately sends it even if the transaction fails, which suits logging. Apex trigger subscribers run asynchronously in batches, can retry with EventBus.RetryableException, and can resume from a checkpoint with setResumeCheckpoint.
  5. Both mechanisms can deliver duplicates, so I design consumers to be idempotent and key them on a business identifier such as a policy number plus a version, not on arrival order.

Follow-up

  • An external subscriber was down for six hours. How does it catch up, and what if it was down for four days?
  • When would you choose Publish Immediately over Publish After Commit?
  • How would you stop a downstream system from applying the same policy update twice?

Walk me through how you would design a RESTful API in Salesforce to expose annuity policy data to an external

Medium · Architecture, Integration, and Data

Walk me through how you would design a RESTful API in Salesforce to expose annuity policy data to an external portal.

Approach

  1. Check first whether the standard REST, Composite or GraphQL API already covers the need. If the portal needs a shaped, stable contract, I write an Apex REST class: @RestResource(urlMapping='/v1/policies/*') with @HttpGet, served at /services/apexrest/v1/policies/{policyNumber}. The version sits in the URL so the contract can change later.
  2. Return a DTO wrapper class serialised to JSON rather than raw sObjects. That controls exactly which fields leave the org and keeps the portal independent of internal field API names. Look policies up by an External ID policy number, which is indexed and unique.
  3. Secure it. The portal authenticates through a connected app with OAuth 2.0, using the JWT bearer or client credentials flow for server-to-server calls, as a dedicated least-privilege integration user. Apex REST runs in system mode by default, so I declare the class 'with sharing' and query WITH USER_MODE so sharing and FLS apply.
  4. Handle lists and errors. Paginate with a keyset cursor (WHERE Id > :lastId ORDER BY Id LIMIT n) instead of OFFSET, which caps at 2,000 rows. Set RestContext.response.statusCode to 400, 404 or 500 with a consistent JSON error body, and support a modifiedSince filter on SystemModstamp for incremental sync.
  5. Test with RestContext.request and response set up in unit tests. Watch the org's daily API request allocation and the synchronous heap limit (6 MB) when a policy has many related records.

Follow-up

  • How do you make sure a portal user can only ever see their own customer's policies?
  • The policy model gains new fields and one field is renamed. How do you change the API without breaking the portal?
  • How would the portal efficiently fetch only the policies changed since its last sync?

How do you secure an integration between Salesforce and an external third-party system?

Medium · Architecture, Integration, and Data

Approach

  1. Separate inbound from outbound. For inbound calls into Salesforce I use a connected app (or external client app) with OAuth 2.0: the JWT bearer flow with a certificate, or the client credentials flow, for server-to-server. Scopes stay narrow, IP ranges are restricted where possible, and refresh-token policies are set. No stored username and password.
  2. Run the integration as a dedicated API-only user with a minimal permission set, so the blast radius of a leaked credential is limited to the objects and fields that integration needs. In Apex REST endpoints, enforce sharing and FLS (with sharing, WITH USER_MODE) and validate every input.
  3. For outbound callouts I use Named Credentials with External Credentials, so endpoints and secrets never appear in code or metadata (callout:Policy_Admin/...). Where the partner requires it, I add mutual TLS with a certificate held in Certificate and Key Management.
  4. Protect the data itself. TLS 1.2+ in transit, encryption at rest for sensitive fields such as tax IDs (Shield Platform Encryption where licensed), and masking those values in debug logs, error messages and integration logs.
  5. Monitor and rotate. Review Login History, API usage and Event Monitoring for the integration user, alert on unusual volume, and plan certificate and secret rotation with an overlap window so both old and new credentials work during cutover.

Follow-up

  • The third party only supports a static API key. Where do you store it and how do you rotate it?
  • How would you rotate the JWT signing certificate without an outage?
  • What should never appear in an integration error log, and how do you enforce that?

What are the architectural differences between implementing a solution via Lightning Flow versus writing custo

Medium · Architecture, Integration, and Data

What are the architectural differences between implementing a solution via Lightning Flow versus writing custom Apex?

Approach

  1. Frame both as automation in the same transaction. Record-triggered flows and Apex triggers share the same governor limits and the same save sequence, so the choice is about maintainability, complexity and control, not about escaping limits.
  2. Flow strengths. Before-save flows update fields on the triggering record without DML and are fast. Admins can maintain flows, scheduled paths and screen flows cover common needs without code, and Flow Trigger Explorer sets the order among flows on an object.
  3. Apex strengths. Complex logic with maps and sets across a bulk batch, fine-grained error handling with try/catch and partial-success DML, unit tests with real assertions running in CI, readable diffs in Git (flow XML is hard to review), and callouts with full control. Record-triggered flows can only make callouts from an asynchronous path.
  4. Name the failure modes. A flow with a Get Records or Update element inside a loop hits the 100-query or 150-DML limit on bulk loads. A trigger and a flow that both update the same field on one object make behaviour depend on the save sequence. I pick one automation strategy per object and document it.
  5. Combine them where it fits. A flow handles the orchestration and calls an @InvocableMethod Apex action for the heavy or reusable logic. That keeps the business-facing steps visible to admins while the tricky part stays tested in code.

Follow-up

  • A before-save flow and a before trigger both set the same field. Which value is saved, and how would you remove the ambiguity?
  • How would you test a record-triggered flow as part of a deployment pipeline?
  • A flow works for single records but fails on a data load of 10,000 rows. What do you look for?

Read latency spikes on a sixty-second sawtooth

Medium · cache stampede · single-flight · ttl

The cached listing read path serves about 14k reads/second at an 85% hit rate. p99 sits at 35 ms for 57 seconds, jumps to 900 ms for 3, and repeats. During each spike the primary shows several hundred identical listing queries starting within the same millisecond, all carrying one large tenant's id. Cache entries use a 60-second TTL. Give the mechanism, the ordered checks, the fix, and the correctness hazard your fix must not introduce.

Approach

  1. Match the period to a configured number before theorising about load. A spike every 60 seconds against a 60-second TTL is an entry expiring, and you confirm it by correlating spike timestamps with the entry's write time rather than with the traffic curve. If the period had matched a cron or a GC interval instead, this is a different investigation.
  2. Establish the concurrency of the miss. Several hundred identical queries in one millisecond means the miss path has no coalescing: every request that arrives between expiry and repopulation recomputes. The herd size is that key's arrival rate times its recompute time, so at 1.2k reads/second for the hot key and a 250 ms recompute you expect about 300 concurrent misses, which matches what is observed.
  3. Add single-flight on the miss path so one caller per key recomputes under a short-lived lock while the rest wait for its result. Prefer stale-while-revalidate where the read tolerates it: return the expired value immediately and refresh asynchronously, which removes the latency spike rather than serialising it into a queue of waiters.
  4. De-synchronise the keys. Write TTLs with jitter, for example 60 seconds plus or minus 10%, so a deploy or a mass invalidation does not align every key on the same second and turn a per-key herd into a fleet-wide one.

Follow-up

  • The same sawtooth appears on a key that is invalidated on write rather than expired. Is that the same bug?
  • How does your answer change if the recompute takes 4 seconds instead of 250 ms?

Suggested practice checklist

The plan follows the reported loop: fundamentals and bulk-safe Apex first, then integration and large-data design, then delivery habits, then the behavioral stories, ending in a full spoken run-through.

Day 1 — Platform fundamentals sheet

  • Write a one-page comparison of SOQL and SOSL covering query shape, return types and when each fits.
  • List the order of execution from validation through triggers, flows and commit, and mark where a before-save trigger and an after-save flow each run.
  • Write a Role versus Profile explanation with one example of each controlling access.

Deliverable: A one-page fundamentals sheet with the SOQL/SOSL comparison, the order of execution and the Role/Profile example.

Day 2 — Bulk-safe Apex and async choices

  • Write a trigger and handler that touch related records, first with a query inside the loop, then refactored to a Set, a Map and one DML.
  • Write a test that inserts 200 records and checks Limits.getQueries() and Limits.getDmlStatements().
  • Build a table comparing Batch Apex, Queueable and Future methods on volume, chaining and callouts.

Deliverable: A refactored trigger with its 200-record test and a Batch/Queueable/Future comparison table.

Day 3 — Integration design

  • Outline a REST endpoint for annuity policy data: resource names, authentication, versioning, error responses and pagination.
  • Write a checklist for securing a Salesforce-to-third-party integration, then compare Platform Events with Outbound Messages in your own words.

Deliverable: An endpoint outline, a security checklist, a Platform Events versus Outbound Messages note and a solved idempotency exercise.

Day 4 — Large data volumes and ETL

  • Write your answer for querying and updating millions of records: selective filters, Bulk API, batch size and parent-ordered loads.
  • Write a short account of an ETL load you ran (Informatica or the nearest tool), covering upserts, error handling and reconciliation.

Deliverable: A spoken LDV answer, a written ETL project account and a solved backfill exercise.

Day 5 — Flow versus Apex and delivery habits

  • Write a decision guide for Flow versus custom Apex with three example requirements and your pick for each.
  • Outline a deployment standard for five developers sharing an org: branching, pull request checks, validation deploys and release steps using Git and DevOps Center.
  • Write a code review checklist you would use on a junior developer's pull request.

Deliverable: A Flow/Apex decision guide, a deployment standard outline and a code review checklist.

Day 6 — Behavioral story bank

  • Write STAR notes for explaining a technical roadblock to a business stakeholder and for a delayed project.
  • Write STAR notes for an inclusive collaboration that changed an outcome.
  • Write your goal-setting method with one skill goal and one delivery goal tied to a business result.

Deliverable: Four STAR outlines, each ending in a business-impact line, plus a goal-setting method.

Day 7 — Full spoken run-through

  • Answer aloud, in sequence: bulkification, order of execution, the policy REST API design, the LDV question and the delayed-project story.
  • Record yourself, then cut filler and make sure each technical answer ends with a stated trade-off.
  • Prepare three questions for the recruiter and panel about the team, release process and the Developer II or Senior expectations.

Deliverable: One recorded run-through of five answers with notes on the weakest, and a list of three questions to ask.

Behavioral stories and EPIC values

Candidates report that behavioral questions run alongside the technical ones and are framed by the EPIC values (Empowered, Passion, Integrity, Caring): accountability, adapting to change and delay, collaborating inclusively, and explaining technical issues to business stakeholders. For a Salesforce developer, the strongest stories involve a release, an integration, a data load or a process change where you made a specific decision and can state its business effect. Use STAR and spend most of the time on your own reasoning and result.

  1. Think of a flaw you found in an interface between two systems: how did you raise it with stakeholders, and how was it resolved?

How do you handle bulkification in your code to ensure you do not hit governor limits?

Medium · Salesforce Technical Fundamentals

Approach

  1. Open with the mechanism: a trigger receives up to 200 records per chunk in Trigger.new, so logic must work on collections, and the per-transaction limits (100 synchronous SOQL queries, 150 DML statements) are what a query or DML inside a loop breaks.
  2. Show the pattern: collect related ids into a Set, run one SOQL with an IN clause into a Map<Id, SObject>, loop over Trigger.new reading from the map, add changes to a List and issue a single DML after the loop. Keep SOQL and DML out of helper methods that are called from loops too.
  3. Describe the structure: one trigger per object delegating to a handler class, Trigger.oldMap comparison so work runs only on changed fields, and a static set of processed ids if recursion is a risk.
  4. Say how you prove it: a test that inserts 200 or more records in one call and checks Limits.getQueries() and Limits.getDmlStatements(). When one transaction cannot hold the volume, hand off to Queueable or Batch Apex.
  5. Frame it as a story if you can: a bulk load that failed with a too-many-SOQL-queries error, the root cause, the refactor, and the measured result.

Follow-up

  • The trigger must call an external service for each record. How do you handle callout limits in bulk?
  • How do you stop a trigger from running twice when a flow updates the same record?
  • When would you move work out of the trigger into Batch Apex?

Describe your experience using ETL tools like Informatica to move data into Salesforce.

Medium · Architecture, Integration, and Data

Approach

  1. Be honest about your exposure. If you have used Informatica, describe the pipeline in one sentence (source, mappings, target object, schedule). If you have not, say so and map the closest tools you have used, such as Data Loader or the Bulk API, to the same concepts.
  2. Cover load design: an external id field and upsert so a rerun does not create duplicates, parents loaded before children, lookups resolved through external ids, and explicit handling of nulls, picklist values and data types.
  3. Cover volume: the Bulk API for large loads, tuned batch sizes, child rows sorted by parent id to reduce row-lock contention, and a plan for triggers, flows and validation rules during a migration (bypass them deliberately and restore them).
  4. Cover operations: incremental extraction using a last-modified watermark, an error file you can reload on its own, and a reconciliation of source row counts against Salesforce counts after each run.
  5. Close with numbers from your own project: rows moved, runtime and error rate before and after your change.

Follow-up

  • How would you restart cleanly after a load fails halfway through?
  • How do you keep a rerun from creating duplicate records?
  • What do you do with triggers and flows while a bulk load is running?

Tell me about a time you had to explain a highly technical roadblock to a non-technical business stakeholder.

Medium · Behavioral, Leadership, and EPIC Values

Approach

  1. Choose a roadblock with a business consequence, such as a platform limit, an integration constraint or poor data quality, rather than a purely internal one. State it the way a stakeholder would hear it: effect on date, cost or risk.
  2. Show the translation. Replace platform terms with a plain cause in one sentence, for example: I told the product owner that the platform caps how much one operation can process, so the nightly load would stall at its current size.
  3. Bring two or three options with their trade-offs (slower rollout, extra build time, reduced scope), give your recommendation, and ask for one specific decision.
  4. Show how you checked understanding and followed up in writing, then state the outcome. The mistake that sinks this story is a tour of internals with no recommendation.

Follow-up

  • What did you do when the stakeholder pushed back and wanted the original date?
  • How did you know they understood the issue?
  • How would the same explanation change for an executive versus a business analyst?

Describe a situation where a project was unexpectedly delayed. How did you adapt and keep the team motivated?

Medium · Behavioral, Leadership, and EPIC Values

Approach

  1. State what was delayed and why, and own your share of the cause. Opening with blame on another team weakens the whole story.
  2. Describe the re-plan in concrete steps: re-estimate the remaining work, find the critical path, agree with stakeholders what to cut or defer, and say when you told them and what you said.
  3. Keep motivation specific: smaller milestones the team could see finishing, blockers you removed (for example a release conflict or a stuck dependency), and protecting people from constant changes of direction.
  4. Finish with the result and the habit you changed afterwards, such as earlier risk checks, smaller increments or a regular status note. Include the final date compared with the original.

Follow-up

  • Could you have spotted the delay earlier, and how?
  • What did you cut or defer, and who agreed to it?
  • How did you handle a teammate who lost motivation?

Share an example of a time you uncovered a new perspective through inclusion and collaboration with your team.

Medium · Behavioral, Leadership, and EPIC Values

Approach

  1. Pick a moment where you deliberately sought a view you did not have, for example from a business analyst, a support user, a junior developer or another team, rather than a routine meeting.
  2. Say what you assumed before and what the other person pointed out. Be specific about how you made room for it: asking directly, a walkthrough of the design, or a review session.
  3. Show the change it caused in a requirement, design, test or rollout, and the result. The story needs a visible before and after.
  4. Link it to inclusion in one sentence without lecturing. The mistake to avoid is a story in which you were right all along and the input changed nothing.

Follow-up

  • What did you do when you disagreed with the new perspective?
  • How do you make sure quieter teammates are heard?
  • What did you change in your own routine afterwards?

How do you set personal goals, and how do you ensure they align with the broader business objectives?

Medium · Behavioral, Leadership, and EPIC Values

Approach

  1. Describe a repeatable method: start from what the team and business want this period (ask your manager), turn that into two or three specific, measurable goals, and set a review rhythm.
  2. Give real examples with one skill goal, such as working toward a Platform Developer certification, and one delivery goal, such as cutting failed deployments, each tied to a business outcome and a measure.
  3. Show alignment in practice: you confirmed goals with your manager, and you revised one when priorities changed. Name the goal you changed and why.
  4. The mistake is a list of personal learning goals with no link to business results, or goals too vague to be checked.

Follow-up

  • Tell me about a goal you missed and what you did.
  • How do you rebalance when priorities change mid-year?
  • How do you choose between learning something new and delivering what is due?

Tell me about a time you took the initiative to improve a development process or deployment pipeline.

Medium · Behavioral, Leadership, and EPIC Values

Approach

  1. Choose a process problem you can evidence: manual deployments, changes overwritten in a shared org, failed releases or slow reviews. Give the baseline, such as how often releases failed or how long they took.
  2. Describe what you introduced and why it beat the alternatives: a Git branching convention with pull requests, validation deploys and Apex tests before merge, a review checklist, or a staged pipeline in DevOps Center or Copado.
  3. Cover adoption: how you brought teammates along, how you handled resistance, what you documented, and how rollback worked if the new process failed.
  4. Report the result with a before-and-after measure. The mistake is listing tool names with no story of getting the team to use them.

Follow-up

  • How did you deal with someone who resisted the change?
  • How did you handle a hotfix that could not wait for the normal process?
  • What would you automate next?