Ideas Engineered for Tomorrow
We Engineer Services & Solutions for Your Business Needs
Consulting Services Hire Book Consulting

Hire Salesforce Developers in India

Most teams who set out to hire Salesforce developers in India spend three weeks interviewing administrators, because on paper the two roles look identical. This page is a screening guide first and a pitch second.

Written for whoever owns a Salesforce org from outside India, whether that is North America, Britain or Australasia, and has run out of people who can safely change it.

The hiring mistake that costs a quarter

Salesforce is the only major platform where a person can hold six years of experience, a strong reference and a working knowledge of the product, and still be unable to write code that survives a data load. That's not a criticism of anybody. It's a consequence of how the platform is built. Configuration and code sit side by side in the same org, and a career can be spent entirely on the configuration side while looking, from the outside, exactly like an engineering career.

The result is predictable. A team posts for a Salesforce developer, describes work that is mostly declarative, receives a hundred applications, hires someone competent, and then discovers four months later that the one thing they actually needed was a bulk-safe trigger and nobody on the team can write one. The reverse happens too. A team hires a genuine Apex engineer for an org whose entire problem is that its page layouts and permission sets have never been rationalised, and pays engineering rates for work an experienced administrator would have finished faster.

So the useful thing this page can do is help you work out which person you need, then give you the questions that separate the two. The commercial part is short and sits at the bottom. If you read the screening sections and then run the hire yourself, that's a fine outcome.

Administrator, developer or architect: which one do you actually need?

Three roles, three different sets of daily work, and one shared job title in most job adverts. Read the descriptions below against your open ticket queue rather than against your org chart.

What an administrator owns

Objects, fields, record types, page layouts and Lightning app pages. Profiles, permission sets and permission set groups. Sharing rules, role hierarchy and org-wide defaults. Reports, dashboards and list views. Data imports, duplicate rules and validation rules. And, increasingly, Flow, which is where the boundary starts to blur. A strong administrator solves a surprising share of what gets filed as a development request, and does it faster than a developer would, because the answer is configuration and they know where every setting lives. If your backlog is mostly requests phrased as I want a field that, or users cannot see, or the report should show, you are looking at administrator work and hiring an engineer for it will slow you down.

What a developer owns

Apex classes and triggers. Lightning Web Components. Test classes and the coverage gate. SOQL and SOSL beyond what a report builder can express. Callouts to external services, named credentials, and the retry and error handling around them. Asynchronous processing. Metadata under source control and a deployment pipeline. A developer is the person you need when the logic has branches, when it has to talk to something outside the org, when it has to process volume, or when it has to be testable and reviewable before it reaches production. The tell in your backlog is any ticket that starts with when this happens, do that, unless, in which case, and then, because that shape does not survive being drawn as boxes on a canvas.

What a technical architect owns

The decisions that are expensive to reverse. Whether a requirement becomes a custom object or a record type on an existing one. Whether a second business unit shares your org or gets its own. How the sharing model will behave when the data volume is ten times larger. Which system is the source of truth for a customer record. Whether a managed package solves a problem cheaply or embeds a dependency you will still be paying for in five years. Architects are not usually the right first hire, and hiring one to write triggers wastes them. They earn their keep at the start of something large, or at the point where an org has become so tangled that the next decision needs someone who can see the whole shape of it.

The hybrid everybody wants

Job adverts routinely ask for a person who administers the org, writes production Apex, builds components, manages the release pipeline and advises on architecture. That person exists. They are rare, they are expensive, and they are almost never available at the moment you need them. More importantly, that combination is often the wrong shape for the work. An org with real engineering requirements and real configuration debt is usually better served by two people who each do one job well and talk to each other, than by one person context-switching between both and doing neither at depth.

How to decide in an afternoon

Take the last thirty tickets your Salesforce queue has received. Sort them into three piles: things a well-configured setting would fix, things that need code, and things that are really questions about what the org should be. Whichever pile is largest tells you the hire. If the code pile is small but contains the two most urgent items, you probably want a developer part-time rather than an administrator full-time. If the third pile is largest, stop hiring and book an architecture review, because filling a seat before that conversation tends to produce work that gets thrown away.

Why do governor limits decide who is a real Salesforce developer?

If you take one screening idea from this page, take this one. Apex runs on shared infrastructure, so the platform caps what a single transaction may consume: how many queries it issues, how many rows it retrieves, how many DML statements it runs, how much CPU it burns, how much heap it holds, how many callouts it makes. Exceed a cap and the transaction does not slow down or degrade. It throws an uncatchable limit exception and everything in it rolls back. The specific figures move between releases and differ between synchronous and asynchronous contexts, so treat any number a candidate quotes from memory as trivia and check the current values in the Apex Developer Guide yourself. What matters is whether they design as though the caps exist.

The transaction is the unit, not the record

This is the mental model that separates the two groups of candidates. A general developer arriving from Java or C# thinks in terms of an object and a method that acts on it. Apex looks close enough to Java that the habit survives the language change, and it is wrong here. Salesforce hands a trigger a collection of records, not one record, and every limit is counted across the whole transaction. So the question is never what does this code do to a record. It is how many queries does this code issue by the time the transaction ends, and the answer depends on how many records arrived.

SOQL inside a loop

Here is the canonical failure. A trigger iterates the incoming records and, inside the loop, queries for the related account of each one. One record, one query, works perfectly. A user saves a single record in the UI and nothing goes wrong for months. Then somebody runs a data load, or an integration posts a batch, or a Flow updates a set of records in bulk, and the same code issues one query per record until it hits the cap and the entire operation fails. The load rolls back, the integration retries into the same wall, and somebody opens a ticket saying Salesforce is broken.

The fix is not clever. Query once outside the loop for every related record you will need, put the results in a Map keyed by id, and read from the Map inside the loop. Any developer who has genuinely written production Apex will produce that rewrite without prompting. Candidates who have only touched Apex will describe the problem as a performance issue, which is the answer that should end the interview politely.

Bulkification is a correctness property

The same discipline applies to writes. Collect records into a List and issue one DML statement after the loop rather than saving inside it. It applies to invocable Apex called from Flow, where the method signature takes a List precisely because Flow may call it with many records at once, and a method written to handle position zero of that list will quietly process one record out of two hundred. It applies to callouts, where a synchronous external call per record will exhaust the callout cap long before it exhausts your patience. And it applies to anything a candidate writes in a take-home exercise, which is why the exercise should always specify that the code will run against a bulk load.

Why 200 is the number that matters

Salesforce chunks records into batches when it hands them to a trigger, and for most operations the chunk is two hundred records. That is why unbulkified code so often survives testing and fails in production: a developer tests with one record, a QA analyst tests with five, and the first time the code sees a real chunk is the day someone loads a spreadsheet. It also means that passing at two hundred is not proof of safety, because a data load of ten thousand records fires the trigger fifty times, each with its own transaction, and code that accumulates state in static variables across those invocations behaves differently again. Ask a candidate what happens on the second chunk. The good ones have been bitten by this.

CPU time, heap and the limits nobody rehearses

Query counts get all the attention because they are easy to explain. In an org that has been running for a few years, the cap that actually fires is CPU time, and it fires because a single user action now triggers a chain of automation nobody owns end to end: a before trigger, three record-triggered Flows, a managed package handler, a roll-up recalculation, and an after trigger that updates a parent and starts the whole thing again on a different object. Each piece is defensible. The sum exceeds the cap. Heap is the other quiet one, usually hit when a batch job loads far more data into memory than it needs, or when someone builds a large string in a loop. A developer worth hiring will ask to see the debug logs and the limit consumption before proposing a fix, rather than deleting the most recently added Flow on the theory that it must be the culprit.

Why your sandbox will not catch any of this

A developer sandbox holds your metadata and almost no data. Every one of the failures above is a function of volume, chained automation and real ownership patterns. So the code passes, the tests pass, the deployment succeeds, and the failure arrives in production during a month-end load. This is not a reason to distrust sandboxes. It is a reason to insist that anything touching volume gets tested against a data set large enough to be interesting, and that the developer knows how to read limit consumption out of a debug log instead of guessing.

Apex, judged properly

Apex is a small language with strong opinions and a very specific set of ways to get it wrong. What follows is what a senior developer does by habit, which doubles as a checklist for reviewing code a candidate shows you.

One trigger per object, and the framework question

Salesforce allows several triggers on the same object and gives you no way to control the order in which they run. That is the entire argument for the one-trigger-per-object convention: a single trigger file per object, containing no logic at all, which delegates to a handler class where the order is explicit and visible. Ask a candidate what they do about this and you will get one of three answers. Some describe a hand-rolled handler with methods named for each context. Some name a published framework, and the well known ones are Kevin O Hara sfdc-trigger-framework for something lightweight, the fflib Apex Enterprise Patterns set for larger estates with a domain and selector layer, or the Trigger Actions Framework where the ordering is configured in custom metadata rather than compiled in. Some have never thought about it, which tells you they have not maintained an org with more than a handful of automations on one object.

The follow-up question is better than the first: how do you stop a trigger from re-entering itself when its own update fires the same trigger again. The expected answer involves a static variable, usually a Set of record ids already processed, held for the life of the transaction. The interesting part is what they say next, because a static guard that is set too broadly will silently skip legitimate processing on the second chunk of a data load. Someone who volunteers that trade-off has debugged it.

Asynchronous Apex, and picking the right one

There are four asynchronous mechanisms and they are not interchangeable. Getting this choice right is most of what separates a mid-level developer from a senior one.

A future method is the oldest and the most limited. It is a static void method annotated with future, it accepts only primitives and collections of primitives rather than sObjects, it cannot be chained, and you cannot monitor it beyond the Apex Jobs list. It survives mostly in older orgs and in the one case it still handles neatly, which is escaping a mixed DML restriction. If a candidate reaches for it first in a new build, ask why.

Queueable is the sensible modern default for a unit of work that should happen after the transaction. It takes complex types including sObjects, returns a job id you can query and monitor, and can enqueue another job from inside itself, which gives you chaining for work that has to run in sequence. Add the AllowsCallouts interface when it needs to talk to an external system, and attach a Finalizer when you need to know whether the job succeeded or failed and react to it.

Batch Apex is for volume that cannot fit in one transaction at all. You implement start, execute and finish. The start method returns a query locator describing what to process, the execute method runs against each chunk with its own fresh set of governor limits, and the finish method runs once at the end, which is where notification and chaining belong. The scope size is yours to choose, and choosing it badly is the usual cause of a batch that fails halfway through: too large and each chunk hits CPU or heap, too small and the job takes hours and burns job slots. Ask a candidate how they picked a scope size on a real job and whether they made it configurable, because hard-coding it means every future tuning change is a deployment.

Scheduled Apex is the clock, not a processing model. It implements Schedulable, it is scheduled with a cron expression, and in almost every serious use it exists only to kick off a batch job. Code that does the actual work inside the scheduled class is a smell, because it inherits synchronous constraints for no reason.

Platform Events belong in the same conversation even though they are not strictly asynchronous Apex. Publishing an event and letting a trigger on that event do the work decouples the publisher from the consumer and gives you a clean way to move processing out of a user transaction. A candidate who reaches for events when the requirement is genuinely fire and forget is thinking about the org rather than the ticket.

Test coverage is a deployment gate, not a quality signal

Salesforce will not accept Apex into production unless the org meets its coverage requirement, which has long stood at three quarters of your Apex lines, evaluated across the org and with individual trigger requirements alongside it. Verify the current rule in Salesforce documentation before you plan a release around it. The important thing for hiring is what that number does to behaviour. Because coverage is measured in executed lines and nothing else, it is entirely possible to satisfy the gate with tests that instantiate a class, call every method, assert nothing, and wrap the whole thing in a try block that swallows exceptions. Orgs full of exactly those tests are common, and they are worse than no tests, because they produce a green build and a false sense of safety.

What a good test looks like is easy to describe and rare to find. It creates its own data rather than relying on whatever happens to be in the org, usually through a shared test data factory. It exercises the bulk case with a couple of hundred records, not one. It includes at least one negative path where the code should refuse to do something, and asserts that it refused. It uses Test.startTest and Test.stopTest to get a clean set of limits and to force asynchronous work to complete before the assertions run. It uses a mock for every callout, because a real callout in a test simply is not allowed. And its assertions name what they are checking, so a failure three years from now tells the next developer what broke rather than that a number was not another number.

Sharing, security and the things a code reviewer checks

Apex runs in system context by default, which means it ignores the sharing rules that constrain the user who triggered it unless you tell it otherwise. Declaring a class with sharing makes it respect record-level access. That is not the whole story: field-level security and object permissions still need enforcing separately, either by checking access explicitly or by using the security-enforced clause in your SOQL or the platform stripInaccessible call. A candidate who knows the difference between record access and field access, and can say which of the two the with sharing keyword covers, has been through a real security review. Alongside that, look for parameterised queries or escaped variables in any dynamic SOQL, since string concatenation into a dynamic query is the SOQL injection route, and for the absence of hard-coded record ids, which is the single most reliable sign that code has never survived a sandbox refresh.

Lightning Web Components, and reading the age of an org

The user interface layer tells you more about an org, and about a candidate, than almost anything else on a CV. Salesforce has shipped three generations of custom UI technology and most real orgs contain all three at once.

What LWC actually asks of a developer

Lightning Web Components are the current model and they are close to standard web components, which is the point. A component is a folder with an HTML template, a JavaScript class extending LightningElement, a meta configuration file that declares where the component may be dropped, and optionally a CSS file and a Jest test. Modern JavaScript applies: modules, classes, decorators. The Salesforce-specific parts are the decorators for reactive properties and wired data, the base component library, the design system that keeps it looking native, and the rules about how components talk to each other.

Data reaches a component two ways. The wire service pulls record data declaratively through the Lightning Data Service, which caches, keeps multiple components on a page in agreement, and updates the record without you writing a line of Apex. That is the right default for straightforward record access. Imperative Apex is for everything else: a method annotated as callable from the UI, marked cacheable when it only reads, returning a promise your component awaits. The interview question worth asking is when they would choose one over the other, because a developer who wires everything is going to struggle the moment the requirement involves conditional logic, and one who calls Apex for everything is throwing away the caching and consistency the platform already gives them.

Component communication is the other place experience shows. Parent to child is a public property. Child to parent is a custom event, and whether that event has bubbles and composed set correctly determines whether it escapes the shadow boundary or vanishes. Between components with no relationship at all, Lightning Message Service is the supported route. Candidates who solve every communication problem by dispatching an event onto the document object have not read the shadow DOM rules and will produce components that work in a demo and break inside a record page.

What the mix of LWC, Aura and Visualforce tells you

Visualforce is the oldest layer, page-based, rendered server-side, and carrying a view state whose size limit is the classic reason an old page starts throwing errors as the data behind it grows. If a substantial part of your org still runs on Visualforce pages, the org predates the Lightning era and has not been through a UI modernisation. That is not automatically a problem. Visualforce still works and there are pages where rewriting buys nothing.

Aura components are the middle generation. They use their own component markup, a separate controller and helper file structure, and an event model with application and component events that is genuinely harder to reason about than the LWC one. An org built mostly in Aura was probably built between the arrival of Lightning Experience and the point where LWC became the default. Aura still runs, and Aura and LWC interoperate on the same page, with an Aura component able to contain an LWC but not the other way round.

So a quick read: heavy Visualforce means an older org with a modernisation project waiting to be funded. Heavy Aura means a mid-generation build where new work should go into LWC and existing components get migrated as they are touched. Mostly LWC means someone has been maintaining the front end deliberately. A candidate who can look at your component list and tell you which of those you are, and roughly what a migration would cost in effort, is thinking about your org rather than about their next ticket.

The migration question you will be asked to fund

At some point a developer will propose rewriting Aura components into LWC. The honest position is that a wholesale rewrite is rarely worth funding on its own. The defensible version is incremental: new work is LWC, any Aura component being changed substantially gets converted as part of that change, and anything nobody has touched in three years is left alone. Ask a candidate to justify a migration in terms of what it makes possible or cheaper. If the only argument offered is that the old thing is old, you have your answer about how they will spend your budget.

When is Flow right and when does it become a liability?

This is the live argument in the Salesforce world and it deserves a straight answer rather than a diplomatic one. Salesforce has consolidated its declarative automation onto Flow and retired the older tools, which means Flow now carries logic that used to be split across several mechanisms. That consolidation is good. What has come with it is a genuine problem.

What Flow does well

Record-triggered Flows handle a large class of requirements properly and cheaply. A before-save Flow that sets a field on the record being saved is fast, because it modifies the record in memory before it is written rather than issuing another update. Screen Flows give you guided processes that a business team can adjust without a release. Scheduled Flows handle nightly housekeeping. Approval routing, notifications, related record creation, field derivation: all of it belongs in Flow, and insisting on Apex for that work makes your org more expensive to run and takes ownership away from the people closest to the process.

Where it turns

The trouble starts when Flow is asked to do things it was not shaped for. A Get Records element inside a loop is the declarative version of SOQL in a loop, and it fails the same way for the same reason, except that it is harder to spot because a canvas does not look like a nested query. Update elements inside loops do the same to your DML count. Deep branching turns into a canvas that will not fit on a screen, where the logic is spread over dozens of decision elements and no reviewer can hold it in their head. There is no meaningful diff between two versions of a Flow, so code review becomes a matter of opening both and squinting. There is no unit test. And the moment your logic depends on state carried across records, or on catching a specific exception, you are past what the tool expresses.

The compounding problem is that nobody rewrites. A Flow built for a simple case grows an element at a time, each addition perfectly reasonable, until you are looking at an artifact that nobody dares change and nobody can safely delete. The person who built it has moved on. It has no fault paths, so when it fails it emails an error to an address that no longer exists. That is the artifact a new developer inherits, and it is the most common thing we are asked to unpick.

The mixed estate problem

Where it gets genuinely hard is an object with both. Salesforce publishes an order of execution describing how triggers, validation rules, Flows, roll-ups and sharing recalculation interleave on a save, and it is worth reading rather than remembering, since it has been revised as the platform has changed. What matters practically is that a before-save Flow and a before trigger on the same object are both modifying the same record at slightly different moments, an after-save Flow can update a record and re-enter the trigger, and a developer debugging an unexpected field value has to establish which of the two set it last. Splitting the automation for one object across both models without writing down who owns what is how orgs end up with fields that change value for reasons no single person can explain.

Setting the boundary and writing it down

The practical answer is a written rule per object, agreed once and enforced in review. Something like: field derivation and record creation live in Flow, anything with a callout or a loop over related records lives in Apex, and no object carries both a record-triggered Flow and a trigger unless the split is documented in the handler class. That rule matters more than which side of the line you draw. Ask a candidate what rule they have used and whether they enforced it. A developer who says it depends and stops there is not going to give your org a policy. One who describes the rule they applied at their last org, and the case where they had to break it, will.

The org as an inherited artifact

Technical debt in a Salesforce org behaves differently from debt in a codebase you own outright, and the difference is worth understanding before you hire someone to work in one.

Why nobody can read the whole thing

In an ordinary application, the logic is in files, the files are in a repository, and a determined engineer can read all of it in a week. A Salesforce org is not like that. Behaviour is distributed across Apex, Flows, validation rules, formula fields, roll-up summaries, assignment rules, sharing rules, workflow leftovers from before the consolidation, managed package logic you cannot open, and configuration in custom settings and custom metadata that changes what all of it does. Some of it lives in metadata you can retrieve. Some of it lives only in the org. A field can be set by six different mechanisms and the only way to know which one won is to reproduce it with debug logging on.

The second difference is that an org accumulates by addition, not by revision. Nobody deletes a field, because deleting a field might break a report somebody in finance runs quarterly. So the org grows fields nobody populates, validation rules with conditions that can no longer be true, page layouts assigned to profiles with no users, and permission sets granting access to objects that were decommissioned. None of it is dangerous on its own. Collectively it makes every change slower and every estimate less reliable, and it is the reason a request that would take two days in a clean org takes two weeks in yours.

What a first-month audit should produce

Any developer joining an inherited org should spend part of the first weeks producing something you can read. Not a full documentation project, which nobody finishes. Something narrower and genuinely useful: for each of your busiest objects, a single page listing every piece of automation that fires on it, in the order it fires, with a note on what each one is for and whether anyone still needs it. Alongside it, the Apex classes with no coverage worth the name, the components still on the older UI generations, the managed packages installed and what depends on them, and the three or four things that would break first under twice the current data volume.

That document is also the best test of a candidate you will get. Producing it requires reading debug logs, tracing a save through the order of execution, working out what a Flow does without a diff, and asking your business users questions in language they understand. Someone who can do that can do the rest of the job.

Managed packages and the parts you do not control

Installed packages bring code you cannot read, triggers you cannot reorder, and objects whose behaviour you cannot change. They also consume the same limits your own code does, which is why a CPU timeout can be caused entirely by something you did not write. A developer working in an org with several packages needs to be comfortable establishing what a package contributes to a transaction, working around it rather than through it, and telling you honestly when the correct answer is a support case with the vendor rather than more code on your side.

Deployment, and why it worked in the sandbox means something here

Every platform has a deployment story. Salesforce has three, they coexist, and which one your org uses tells you how the team has been working.

Change sets, and what they cost you

A change set is assembled by clicking through a list in one org and uploading it to another over a deployment connection. It requires no tooling and no engineering skill, which is why it is still everywhere. It also has no version control, no history beyond the org, no way to delete components, and a component picker that will let you forget a dependency and find out at deploy time. Assembling one for a release of any size is an afternoon of careful clicking that cannot be repeated reliably. An org that deploys exclusively by change set is an org where nobody can tell you what changed last month or roll it back.

The metadata API and source-driven development

Underneath everything sits the Metadata API, which retrieves and deploys components described in a manifest. Salesforce DX is the modern working model built on top of it, driven through the Salesforce CLI. Metadata lives in your Git repository in a source format designed to be diffed, the CLI pushes and pulls it, and scratch orgs give a developer a disposable environment created from that source rather than a shared sandbox everyone is fighting over. Packaging, where a body of metadata is versioned and installed as a unit, is the mature end of the same road.

The practical wins are the ones to hire for. A pull request that shows what actually changed. A pipeline that runs a validation-only deployment against the target org so a failing test fails your build rather than your release window. The ability to run a chosen subset of tests instead of everything, which matters enormously in an org where the full suite takes an hour. And deletions handled properly through a destructive changes manifest instead of somebody remembering to delete a field by hand in production. Ask a candidate to describe their last release pipeline end to end. The answer separates people who have engineered a release process from people who have performed one.

Sandboxes, and the sentence with real meaning

It worked in the sandbox is a joke everywhere else. On Salesforce it is a diagnosis, because sandboxes differ from production in ways that reliably break things. Data volume is the obvious one, already covered. Underneath it sit several others. Record ids change on a refresh, so any id hard-coded in code or configuration points at nothing. Custom settings and some configuration data do not always come across, so code branches on a value that is absent. Integrations point at test endpoints or at nothing at all, so a callout that fails silently in the sandbox fails loudly in production. Users, roles and ownership are different, so a sharing bug is invisible until real ownership patterns exist. Email deliverability is restricted by default, so a notification path is genuinely untested. And the automation running in production may be one release ahead of what the sandbox has, if somebody made a change directly in production.

That last one is the killer, and it is common. A hotfix goes into production, nobody back-ports it, and the next deployment from a sandbox that never received it quietly reverts the fix. The defence is process rather than cleverness: production is not edited, sandboxes are refreshed on a known schedule, and the pipeline validates against production before anything is deployed. A developer who volunteers that as a concern is telling you they have lived through it.

Data: selectivity, volume and the report that times out

Most Salesforce performance complaints arriving as tickets are data problems wearing a user interface costume. The report is slow, the list view spins, the batch job fails at three in the morning. Underneath, a query is scanning far more than it should.

Selective queries and why a filter stops helping

Salesforce runs a query optimizer that decides whether to use an index or scan the object. A filter is only useful if it is selective enough, meaning it narrows to a small enough fraction of the rows for the optimizer to trust the index. The thresholds are published and depend on whether the index is standard or custom and on how large the object is, so read the current large data volume material rather than working from a number in someone's head. The consequence is what matters: a query that ran quickly last year can become non-selective purely because the object grew, with no change to the code at all. Certain filter shapes also defeat indexes outright, among them leading wildcards, negative operators, and formula fields that are not deterministic and therefore cannot be indexed at all. A developer who understands this will look at the query plan before rewriting anything, and will know that custom indexes on the fields you filter by most are requested from Salesforce support rather than created in setup.

Skinny tables, and when to ask

Where reports and list views repeatedly read the same handful of fields across a very large object, Salesforce can create a skinny table: a maintained copy containing only those fields, including both standard and custom, which avoids the join that ordinarily happens between them. It is not a self-service feature. You raise it with Salesforce support, it is created for you, and it comes with real constraints, including that changing the field set means having it rebuilt. It is a genuine tool for a specific problem, and a candidate reaching for it as a first answer to any slow report is reaching too early. The right sequence is to fix the query, then the index, then consider the table.

Skew and the locks it causes

Large volumes bring failure modes that have nothing to do with query speed. Ownership skew is one user owning an enormous number of records, which makes recalculating sharing after any role or hierarchy change extremely expensive. Lookup skew is very many child records pointing at the same parent, which produces record lock contention during parallel loads because each child update briefly locks the parent. Both show up as intermittent errors during data loads that nobody can reproduce on demand, which is exactly the profile of a bug that stays open for months. Salesforce publishes threshold guidance in its large data volume documentation. The mitigations are unglamorous: an integration user who does not own everything, loading in a sensible order, controlling parallelism, and deferring sharing recalculation during a large load.

Archiving and the honest answer about reporting

Sometimes the correct fix is that the data should not be in the object any more. Big Objects hold very large volumes of historical records with a query model that is deliberately restricted, and they suit archived transactional history where you need retrieval but not general reporting. Where the requirement is genuine analytics across years of history, the honest answer is often that the reporting should happen outside the org, with the data replicated to a warehouse and the analysis run there. Where that path is the right one, our data integration services cover the replication and pipeline side rather than a developer seat inside the org.

Screening questions, and the answers that reveal depth

Use these in a technical conversation rather than a written test. What you are listening for is whether the answer comes from having been burned or from having read about it.

Eight questions worth an hour

Ask what happens when a trigger with a query inside its loop meets a data load, and listen for a limit exception and a full rollback rather than for slowness. Ask why there should be one trigger per object, and expect the answer to be about execution order being uncontrollable rather than about tidiness. Ask them to choose between a queueable job and a batch job for a specific piece of work and justify it, since the reasoning matters more than the choice. Ask what they assert in a test for a bulk trigger, and count how quickly they mention two hundred records and a negative case.

Then ask when they would use the wire service instead of calling Apex from a component, which sorts people who have built real Lightning Web Components from people who have copied one. Ask what they do when a record-triggered Flow and a trigger both run on the same object, and listen for order of execution and a written rule. Ask how they would find out why a field on an account keeps changing when nobody edited it, which is a debugging question disguised as a trivia question and is the best single predictor in this list. Finally, ask what they would want to look at first in an org they had just inherited, and see whether they ask you questions back.

A take-home worth setting

Keep it under two hours and make the bulk requirement explicit. A workable brief: on a custom object, when a record is saved, look up a related record, apply a rule that has at least one exception in it, write a result back to a parent, and handle the case where the related record does not exist. Require tests. Say in the brief that the code will be run against a load of several hundred records. Then read the submission for one query outside the loop, one DML statement after it, a test that creates its own data and asserts something specific, and a class declared with sharing. You are not looking for elegance. You are looking for whether the bulk case was designed for or bolted on.

Answers that should end the conversation

A few responses are reliable signals to stop. Describing the SOQL-in-a-loop problem as a performance concern. Quoting exact limit figures with confidence and getting the synchronous and asynchronous distinction wrong. Saying test coverage is handled at the end. Proposing a full rewrite of your Aura components before having seen them. Claiming that Flow is always the right answer, or that it never is, since both positions signal someone who has only worked on one side. None of these are moral failings. They just mean the person isn't the one you want holding your production org.

What seniority actually means for this skill

Years of experience are a poor guide on this platform, because a person can spend five years doing configuration work with the word developer in their title. These bands describe what someone can be handed, which is the only definition that helps you plan.

Early career

Writes Apex under review. Builds a Lightning Web Component from a defined design. Fixes a bug in an existing class once the cause has been identified for them. Writes tests, though they will need pushing on assertions and on the bulk case. Should not be given an unfamiliar org, a production deployment on their own, or anything where the requirement is ambiguous. Genuinely useful on a team with a senior person reviewing, and a false economy on their own.

Mid-level

Takes a feature from a written requirement to a merged pull request without supervision. Knows the asynchronous options and picks between them sensibly. Can debug a limit exception from a log rather than by deletion and retry. Understands the deployment pipeline they are working in, even if they did not build it. The gap at this level is usually judgement about the org rather than the language: they will build exactly what was asked for, correctly, without noticing that the request conflicts with something three objects away.

Senior

Owns an area of the org. Reviews other people's Apex and finds the bulk problem in it. Sets the Flow and Apex boundary and defends it. Builds or fixes the release pipeline. Reads a slow report down to the query plan. Talks to your business users directly and translates what they say into something buildable, which is the part that is hardest to hire for and hardest to fake. This is the level at which a single hire can change how fast your org moves.

Lead and architect track

Decides the data model, the org strategy and the integration pattern. Says no to requirements that would cost more than they return, with reasons your finance director can follow. Plans a migration or a multi-org consolidation. You need this level at the beginning of something large or in the middle of something that has gone wrong, and rarely in between. Handing this person a ticket queue is the most common way of wasting them.

Three situations, and what the right hire looks like in each

These are composite patterns drawn from the shape of briefs that arrive, not accounts of specific engagements. They are here because the same three keep recurring.

The Flow estate nobody can debug

A company runs its operations on Salesforce and has been building automation for four years, all of it declarative and most of it by people who have since left. Opportunity now has eleven record-triggered Flows on it. Saving a record takes several seconds and occasionally throws a CPU timeout. A field that drives commission changes value on its own and three people have separately failed to find out why. Nobody will touch anything, because there is no test and no way to know what depends on what.

This is not a Flow problem, it is an ownership problem, and the hire is a senior developer rather than another administrator. The first month is inventory rather than building: what fires on that object, in what order, and which of it is still needed. Then consolidation, usually merging several Flows into fewer with clear entry criteria, and moving the two or three pieces that carry real branching logic into Apex where they can be tested and diffed. The commission field gets tracked down by turning on debug logging and reading the save through the order of execution, which takes an afternoon once someone knows how. What you're buying isn't code. It's the ability to answer why.

The data load that kills a trigger

A mid-sized business imports records from an external system every night. It worked for two years. Volume has grown, and now the load fails partway through most nights with a limit exception, leaving records half-processed and the operations team reconciling by hand every morning. Under it is a trigger written when the nightly file held forty rows, with a query inside a loop and a callout to a pricing service per record.

This is a well-defined job for a strong mid-level or senior developer and it is measured in weeks, not months. The trigger gets bulkified, with the related data queried once into a Map. The per-record callout moves out of the trigger entirely, either into a queueable job or into a batch process with a sensible scope size, because a callout per record in a synchronous transaction was never going to survive growth. Error handling changes shape too: a failed record needs to be recorded and skipped rather than taking the whole batch down with it, so the morning report tells your operations team which twelve rows need attention rather than that everything failed. Where the load itself is the fragile part rather than the code it triggers, that is integration work and belongs with our CRM integration service rather than with a developer seat.

The org handed over by a departed partner

An implementation partner built the org, delivered it, and the relationship ended. There is no repository. Deployments were done by change set from a sandbox that has since been refreshed. There are eighteen Apex classes, coverage sits just above the deployment gate on tests that assert nothing, and two managed packages are installed that nobody internally can explain. Something needs changing and everyone is afraid to start.

The first task here is not the change. It is getting the metadata out of the org and into a repository so that from this point forward there is a history. Then a real assessment: what the classes do, which tests are load-bearing and which are theatre, what the packages contribute, and where the org will break first. Only then does the requested change get made, with proper tests written around the part being touched rather than a project to retrofit tests everywhere. This work suits a senior developer with release engineering experience, and it is the case where a fixed scope of two to three months beats an open-ended seat, because there is a defined finish line: the org is in source control, the pipeline runs, and your team knows what they own.

How this works with a developer in India

The rest of this page is about the skill. This part is about the practical mechanics, including the part that is genuinely inconvenient.

The overlap window, with the arithmetic shown

Two numbers drive the rest. India holds UTC+5:30 for the whole year and never touches its clocks, so the distance between us only moves when yours change. Take an ordinary office day here, half past nine in the morning through half past six in the evening. In UTC terms that window is 04:00 at one end and 13:00 at the other, and everything below is subtraction from those two points.

Britain does well, with four live hours through winter and five once the clocks go forward. Dubai overlaps almost end to end. Sydney catches roughly three at the tail of its afternoon, Auckland closer to one. North America catches nothing at all. That is arithmetic rather than diplomacy: a day closing at 13:00 UTC has already ended by eight or nine East Coast time, and by five or six on the Pacific side.

If you sit in the United States or Canada, then, live collaboration is a thing you buy rather than a thing you get. What buys it is a shifted roster. An engineer starting at 14:30 IST and finishing at 23:30 works through the New York morning and into the early afternoon. Reaching Pacific business hours means the Indian small hours, which is a genuine ask of the person doing it. Agree the shift before the engagement begins rather than renegotiating it in week three. And treat any offer of round-the-clock cover as a claim to be priced: continuous cover means several people, a handover ritual between them, and coordination effort that lands on your side as well as ours.

What the working week looks like

Written-first is not a preference here, it is a requirement, and Salesforce work suits it better than most. A daily written standup posted before the overlap window starts, in your Slack or Teams, saying what was done, what is next and what is blocked. Tickets in your Jira or Linear, updated by the developer rather than by a manager relaying. Pull requests into your repository with your review rules, and where you have no Salesforce reviewer internally, review happens on our side and the diff still comes to you. Decisions written down in the ticket rather than settled in a call you were asleep for.

A weekly call inside the overlap window is worth protecting even when the week has been quiet, because the things that go wrong on remote engagements are almost never technical. They are a misunderstood requirement that nobody surfaced because raising it felt like admitting confusion. Half an hour a week of talking to the person, not about the tickets, prevents most of it.

Access, and what a developer can see

Salesforce access is worth being deliberate about because an org holds customer data by definition. Developers work in a sandbox, on a named user account of yours, with a profile and permission sets scoped to what the work needs and multi-factor authentication on. Production access is separate, granted when there is a reason, and removed when the reason ends. Where your data is regulated, sandboxes get seeded with masked or synthetic records rather than a copy of production, which also happens to make test data more useful. Whether that is required in your case is a question for your compliance team and your own counsel, not something to take from a web page. Code and metadata live in your repository from the first commit rather than in ours, which is a working practice we would apply anyway. Ownership, confidentiality and data handling are contractual questions, settled in the agreement before work starts, and we would rather your legal team pin that down properly than read a loose version of it here.

If it is not working

Sometimes a match is wrong. The technical skill is there and the working relationship is not, or the org turns out to need a different shape of person than the brief described. The thing that makes that recoverable is not a promise, it is that the work was visible the whole way through: commits in your repository, metadata in your source control, decisions in your tickets, and an org audit document that exists independently of whoever wrote it. Replacement terms and how a handover runs are agreed with you in the engagement documents rather than assumed. What we can say without waiting on that paperwork is that a replacement Salesforce developer reaches you within 48 hours of you flagging it, and the org gets a fresh candidate from the bench rather than the one name you were first asked to accept. What we can say generally is that the less of the work lives only in one person's head, the cheaper any change of person becomes, which is why the documentation habits described above are not administrative overhead.

Ways to structure it

Three shapes cover most Salesforce briefs. Which one fits depends on whether you have a finish line.

A dedicated developer

One person, working only on your org, treated as part of your team and present in your standups. This suits an ongoing roadmap, a product built on the platform, or an org large enough that there is always something. It is also the right shape when you want somebody who accumulates knowledge of your org, which on Salesforce compounds faster than on most platforms.

A scoped project

A defined piece of work with an end: getting an org into source control and onto a pipeline, consolidating an automation estate, a Lightning migration, a performance remediation. Fixed scope suits these because the finish line is describable in advance and progress is visible against it. The inherited-org scenario above is the classic case.

Ongoing maintenance

Part-time, continuous attention for an org that needs a competent pair of hands regularly but not daily. Release cycles need watching, small requests accumulate, and something occasionally breaks. This is the shape teams tend to move to once a larger piece of work has landed, and it is usually the same person continuing at reduced hours.

Getting from a conversation to a working developer

Because we keep engineers on the bench rather than starting a recruitment cycle when a brief arrives, a shortlist against your requirement comes back within 48 hours, and most engagements have someone working in your org within about a week of that. You interview whoever is put forward, and if the fit is wrong you say so and we go again. Where a brief turns out to be wider than one skill, the general hire developers in India page sets out how a mixed-skill team gets assembled, and where the heavy lifting sits on the Java side of a middleware layer rather than inside the org, our Java developers take that end.

Questions buyers ask before hiring

What is the difference between a Salesforce administrator and a Salesforce developer?

An administrator configures the platform: objects, fields, page layouts, permission sets, reports and Flows. A developer writes code that runs inside the platform: Apex, Lightning Web Components, tests and deployment metadata. The skills overlap at Flow and diverge sharply at Apex. Most teams advertising for a developer describe an administrator role, and most candidates who call themselves developers are strongest on the admin side.

How do I test whether a candidate really understands governor limits?

Show them a trigger with a SOQL query inside a for loop and ask what happens when a data load touches a few hundred records. A weak candidate says it is slow. A strong one says the transaction fails once the query cap is reached, then rewrites it to query once into a Map keyed by record id. Ask what changes if the loop contains a DML statement instead.

Should new automation be built in Flow or in Apex?

Flow is right for field updates, record creation, approval routing and anything an operations lead should own without a release. Apex is right for logic with branching depth, callouts, recursion control, bulk processing or anything you need under version control and unit test. The failure mode is not choosing Flow. It is choosing Flow, outgrowing it, and never rewriting.

Is 75 percent Apex test coverage enough?

It is the gate Salesforce applies to production deployments, not a measure of whether your code works. Coverage counts executed lines. It says nothing about assertions. Plenty of orgs pass the gate with tests that call a method, assert nothing and swallow exceptions. Ask a candidate how they test a bulk trigger and listen for two hundred records, a negative case and named assertions.

How do I hire for an org that we inherited with no documentation?

Start with an audit rather than a backlog. Ask the candidate to describe how they would inventory the automation on a single object: triggers, Flows, validation rules, workflow leftovers, managed package logic and anything invocable. A developer who has done this before will talk about ordering and interaction, not just listing. That conversation tells you more than any coding exercise.

What time zone overlap will I get with a Salesforce developer in India?

India sits at UTC+5:30 permanently, with no daylight saving to track on our side. Our office day, half past nine to half past six, falls between 04:00 and 13:00 in UTC terms. Britain gets four live hours of it through winter, five after the clocks move, Dubai nearly all of it, Sydney about three, Auckland about one, and North America nothing. US hours need an evening or overnight roster, settled before the engagement begins.

Can the same developer handle our Salesforce integrations?

Sometimes, and it is worth checking rather than assuming. Building on the platform and moving data between platforms are related but separate disciplines, with different failure modes around matching, deduplication and replay. Where the brief is mostly about keeping two systems in agreement, our CRM integration work covers it directly and is scoped as a project rather than a seat.

Tell us what your org needs

Describe the org and the backlog, and we will tell you whether the answer is a developer, an administrator or neither.

Chat for a quick question. Use the form if you would rather send the requirement in writing.

Send your Salesforce requirement

A short note is enough. We reply within one business day.

We use your details only to reply to this enquiry.