Skip to content
Salesforce

Apex and LWC development with a real release pipeline

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.

  • Code only where Flow stops
  • Trigger framework and bulkification
  • Source-driven CI with the sf CLI
Who this is for

You already have Salesforce. You need it to do something it cannot do yet.

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.

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.

Interfaces beyond page layouts

Guided wizards, editable data tables, record pages that show the right thing first. Lightning Web Components for the console, portals and mobile.

A pipeline instead of a change set

Source in Git, validation in CI, promotion through sandboxes, a rollback plan. Releases become routine rather than a weekend event.

Code or configure

When to write Apex, when to build a Flow, when to build a component

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.

RequirementFlowApexLWC
Simple field updates, notifications, approvalsFirst choiceOverkillNot applicable
Logic across many records in one transactionFragile at volumeBulkified handlerNot applicable
Callouts with retries and error handlingLimited controlQueueable with backoffNot applicable
Guided data entry for usersScreen Flow for simple wizardsBehind the scenes onlyRich, multi-step, validated
Reusable logic called from many placesSubflows, harder to testService classesNot applicable
Large data volumes, scheduled processingAvoidBatch, Queueable, ScheduledNot applicable
Automated tests that run in CIFlow tests, limited scopeApex test classesJest unit tests
Custom UI on record pages, portals, mobileScreen Flow componentsData layer via @AuraEnabledPurpose-built
How we write Apex

Patterns that keep an org alive after year three

  • One trigger per object, logic in handlers

    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.

  • Bulkified by default

    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.

  • Governor limits designed around, not hit

    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.

  • Asynchronous where it belongs

    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.

  • Security enforced in code

    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.

  • Errors you can actually find

    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.

Lightning Web Components

Components users do not fight

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.

  • Lightning Data Service first, Apex only when needed
  • SLDS tokens and base components, minimal custom CSS
  • Accessible: labels, focus order, live regions
  • Jest tests for every component with logic
  • Secrets stay server-side behind Named Credentials
  • Works in the console, on record pages and in Experience Cloud
Testing

Coverage is a floor, not a goal

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.

Where AI helps

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.

Release pipeline

From a feature branch to production without a change set

Salesforce release pipeline: scratch org or dev sandbox, Git pull request, CI validation, then QA sandbox, full-copy staging with UAT, and production; the same artefact is promoted through every environment Scratch org or dev sandbox one feature branch each push Git pull request code review · PMD · diff triggers CI validation sf CLI dry-run deploy · Apex tests · Jest merge: the same artefact is deployed onward, never rebuilt per environment QA sandbox (Partial Copy) regression · integration tests promote Staging (Full Copy) UAT · performance at real volumes sign-off Production release window · rollback plan Hotfixes follow the same path on a shortened schedule. Nothing is edited directly in production.
Source lives in Git. CI validates every pull request against a scratch org. One build is promoted through QA and staging to production, so what was tested is what ships.

Scratch orgs

Disposable orgs created from source for each feature and each CI run. If it cannot be built from the repository, it is not done.

Sandboxes

Developer sandboxes where managed packages or org data are hard to script. Partial Copy for QA, Full Copy for UAT and performance.

CI with the sf CLI

GitHub Actions or GitLab CI running sf project deploy validate, the Apex test suite, PMD rules and Jest. Green build or no merge.

Process

How a feature moves from request to release

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.

  1. Scope

    Requirement, acceptance criteria and the Flow-or-code decision, written down with the reason.

  2. Design

    Data model changes, class structure, limits budget, test plan and rollback approach.

  3. Build

    Feature branch, scratch org, tests written alongside the code, demo at the end of each sprint.

  4. Review

    Pull request with a second engineer's review, static analysis and a green CI run.

  5. UAT

    Your users test in a Full Copy sandbox with real data volumes. Defects fixed on the same branch.

  6. Release

    Scheduled window, release notes, monitoring of errors and limits for the first week.

FAQ

Frequently asked questions

Should we build this in Flow or in Apex?

Flow 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.

What test coverage do you deliver?

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.

Do you use scratch orgs or sandboxes?

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.

Can you take over code written by a previous partner?

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.

Do you use AI tools to write Apex and LWC?

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.

Ready to make AI work in production?

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.