Logic Flow cannot express
Pricing engines, allocation rules, rollups across thousands of records, callouts that must retry. Apex that holds at volume and fails loudly, not silently.
Custom logic and interfaces on the Salesforce platform, written when Flow runs out and bulkified from the first line. Tested for behaviour, shipped through sandboxes and CI rather than change sets at midnight.
We are Salesforce implementation specialists inside an AI-first engineering firm. That means we write platform code the way we write any production code: reviewed, tested, versioned and released on purpose.
Pricing engines, allocation rules, rollups across thousands of records, callouts that must retry. Apex that holds at volume and fails loudly, not silently.
Guided wizards, editable data tables, record pages that show the right thing first. Lightning Web Components for the console, portals and mobile.
Source in Git, validation in CI, promotion through sandboxes, a rollback plan. Releases become routine rather than a weekend event.
The cheapest line of code is the one an admin can maintain in Flow. The most expensive is the Flow that silently fails at 10,000 records. We decide per requirement, and record the reason.
| Requirement | Flow | Apex | LWC |
|---|---|---|---|
| Simple field updates, notifications, approvals | First choice | Overkill | Not applicable |
| Logic across many records in one transaction | Fragile at volume | Bulkified handler | Not applicable |
| Callouts with retries and error handling | Limited control | Queueable with backoff | Not applicable |
| Guided data entry for users | Screen Flow for simple wizards | Behind the scenes only | Rich, multi-step, validated |
| Reusable logic called from many places | Subflows, harder to test | Service classes | Not applicable |
| Large data volumes, scheduled processing | Avoid | Batch, Queueable, Scheduled | Not applicable |
| Automated tests that run in CI | Flow tests, limited scope | Apex test classes | Jest unit tests |
| Custom UI on record pages, portals, mobile | Screen Flow components | Data layer via @AuraEnabled | Purpose-built |
A trigger framework routes each event to a handler class with a bypass switch. No logic in the trigger body, no ordering surprises, one place to look.
Every method takes a list, never a single record. Queries and DML sit outside loops. We test with 200 records because that is what a data load sends.
Salesforce caps a synchronous transaction at 100 SOQL queries, 150 DML statements and 10 seconds of CPU. We budget those limits per feature and move heavy work to asynchronous jobs.
Queueable for chained work and callouts, Batch for large volumes, Platform Events for decoupling, Scheduled Apex for nightly jobs. Each with a retry and a dead-letter log.
with sharing unless there is a documented reason, CRUD and field-level checks on user-facing paths, stripInaccessible on query results, Named Credentials for every callout.
A custom log object with correlation IDs, structured messages and a retention job. Failures in integrations and async jobs are visible on a dashboard, not buried in debug logs.
We reach for LWC when a page layout or Screen Flow cannot give users what they need. Typical cases are an editable line-item table, a validated multi-step wizard, a record page that surfaces the next action, and a portal component.
The discipline is the same as any front-end work. Lightning Data Service and @wire before custom Apex, and the Lightning Design System before custom CSS. Keyboard and screen-reader support from the start. Jest tests for every component with logic, and a performance budget for console pages that load fifty times a day.
When a component calls an external service, such as an LLM summary or a pricing API, it goes through Apex and a Named Credential. Secrets never reach the browser. The integration patterns are the same ones we use everywhere else.
Salesforce will not deploy Apex to production unless at least 75% of it is covered by tests and every trigger has some coverage. That rule exists, and we meet it. It is also easy to satisfy with tests that assert nothing, which is how orgs end up with 80% coverage and no confidence.
Our tests assert behaviour. Each one sets up its own data through a factory and runs the code with a bulk of records. It checks the outcome and the negative case, and never relies on SeeAllData. Callouts are mocked. LWC logic has Jest tests. The whole suite runs in CI on every pull request, so a failing test blocks a merge rather than surfacing in UAT.
We use LLM assistants to draft test scaffolding and edge cases from the code under test, then review and prune them. Our AI QA and testing practice covers the same approach for other stacks.
Disposable orgs created from source for each feature and each CI run. If it cannot be built from the repository, it is not done.
Developer sandboxes where managed packages or org data are hard to script. Partial Copy for QA, Full Copy for UAT and performance.
GitHub Actions or GitLab CI running sf project deploy validate, the Apex test suite, PMD rules and Jest. Green build or no merge.
A contained feature such as a pricing rule or a custom component ships in 2–4 weeks. A module with several objects, integrations and components runs 6–12 weeks in two-week sprints. The approach is on our how we work page; commercial options are on engagement models.
Requirement, acceptance criteria and the Flow-or-code decision, written down with the reason.
Data model changes, class structure, limits budget, test plan and rollback approach.
Feature branch, scratch org, tests written alongside the code, demo at the end of each sprint.
Pull request with a second engineer's review, static analysis and a green CI run.
Your users test in a Full Copy sandbox with real data volumes. Defects fixed on the same branch.
Scheduled window, release notes, monitoring of errors and limits for the first week.
Callouts, Platform Events and middleware patterns, with retries that work.
ExploreTechnical debt, security and limits audit before you add more code.
ExploreInvocable Apex as agent actions, and LLM calls from the platform.
ExploreLLM-assisted test generation and review across stacks.
ExploreFlow first for simple record updates, approvals and screen wizards that an admin can own. Apex when logic spans many records in one transaction, needs callouts with retries, is reused from several entry points, or must run at volume. We write the decision down for each requirement so the next person understands why.
Salesforce requires at least 75% Apex coverage, with every trigger covered, before it will deploy to production. We treat that as a floor, not a target. Our tests assert behaviour, run with 200 records to prove bulk safety, cover negative paths, and never depend on live org data.
Both, for different jobs. Scratch orgs for feature development and CI runs, because they are disposable and reproducible from source. Developer sandboxes where a feature needs org-specific data or managed packages that are awkward to script. Partial and Full Copy sandboxes for QA and UAT.
Yes. We start with an org health check: static analysis, test run, governor-limit hotspots and a dependency map. You get a prioritised list of what to fix, what to leave and what to rewrite, with effort ranges, before we touch anything.
Yes, with review. We use Claude Code and similar assistants for boilerplate, test scaffolding and refactors. Every change is reviewed by an engineer, passes static analysis and the full test suite, and goes through the same pipeline as hand-written code. It speeds up the boring parts; it does not skip the checks.
Tell us about your systems, your data and your constraints. We reply within one business day with a straight answer and a suggested next step.