Glumes ITSalesforce Ecosystem Experts
Back to Blog
Implementation

Why Most Salesforce Implementations Fail — And How to Get Yours Right

Glumes TeamMarch 24, 202614 min read

The five failure modes

After 200+ rescue engagements, the same five patterns keep showing up. Each one has a technical signature you can spot in a code review.

1. Custom object sprawl

Signature: more than 25 custom objects created in year one, half of them ending in _Log__c or _Wrapper__c.

Fix: map every proposed object to a Common Component before building. Account + Contact + Opportunity + Case cover 70% of enterprise use cases when combined with Record Types.

2. Trigger anarchy

Signature: 6 triggers on the same object, mixed with 4 Record-Triggered Flows and 2 Process Builders. Order of execution is undefined.

Fix: one trigger per object, framework-based. Trigger Handler pattern:

public class OpportunityTriggerHandler extends TriggerHandler {
  public override void beforeInsert() { OpportunityService.stampSegment(Trigger.new); }
  public override void afterUpdate()  { OpportunityService.rollupToAccount((Map<Id,Opportunity>)Trigger.newMap); }
}
trigger OpportunityTrigger on Opportunity (before insert, after update) {
  new OpportunityTriggerHandler().run();
}

Turn off all Process Builders. Convert the ones you need to keep into Record-Triggered Flows with clearly ordered priorities.

3. Governor limit surprises in year two

Signature: it worked in UAT with 1,000 records. It times out in production with 500,000.

Fix: design for bulk from day one.

// ❌ Governor-limit trap
for (Account a : accounts) {
  List<Opportunity> opps = [SELECT Id FROM Opportunity WHERE AccountId = :a.Id];
  ...
}

// ✅ One query, in-memory map
Map<Id, List<Opportunity>> byAccount = new Map<Id, List<Opportunity>>();
for (Opportunity o : [SELECT Id, AccountId FROM Opportunity WHERE AccountId IN :accIds]) {
  byAccount.putIfAbsent(o.AccountId, new List<Opportunity>()).add(o);
}

Load-test with the Apex Governor Limits Analyzer and Big Object samples before go-live.

4. Sharing model discovered too late

Signature: week before go-live, someone realizes reps can see every opportunity in the org.

Fix: decide OWD, roles, and sharing rules in week one, not month six. Document the decision:

Object          OWD           Sharing mechanism
Account         Private       Role hierarchy + Account Teams
Opportunity     Controlled    Inherits from Account
Case            Private       Queues + criteria-based rules
Custom_Deal__c  Private       Apex managed sharing (complex hierarchy)

Every custom object gets a sharing decision on the same PR that creates the SObject.

5. No environment strategy

Signature: all changes go through one "Full Copy" sandbox and get click-deployed on Friday nights.

Fix: three-tier + source of truth in Git.

Developer scratch orgs
      ▼  (feature branch → PR)
Integration sandbox   (Copado / Gearset auto-deploy on merge)
      ▼  (release branch)
UAT / Full sandbox    (weekly deploy, automated regression via Provar/UTAM)
      ▼  (tag)
Production            (blue/green via unlocked packages)

The architecture review checklist

Before signing off a Salesforce build, verify:

  • All triggers use one handler per object
  • Zero active Process Builders
  • Every SOQL inside a loop is a bug — CI fails the build
  • Sharing model documented per object, tested with runAs()
  • Metadata in Git with a PR review policy
  • Sandbox refresh policy defined
  • Data archival strategy in place before hitting 10M records per object
  • Field-Level Security audit run against every profile & permission set

Cost of skipping this

Rescue engagements average 4–6× the cost of building it right the first time — mostly because business logic must be reverse-engineered from an org no one owns anymore. Invest in architecture before features.

SalesforceCRMImplementation

Related articles