QuantumNest
Engineeringlightning web components

Twenty deployments of LWC, and what stuck

The framework is excellent. The codebases written in it are uneven. After twenty engagements, the patterns that survive are the boring ones.

QuantumNest Engineering20 Nov 20258 min read
A developer working on interface components on screen
// the components that survive a year of maintenance are the ones you can describe in two sentences.

Lightning Web Components arrived in 2019, and by 2026 every Salesforce front end of any real complexity is built with them. The framework itself is genuinely good. The code people write in it is uneven, and the unevenness is predictable. Having either built or rescued production LWC across twenty client engagements, we keep seeing the same handful of patterns prove themselves at the twenty-four month mark, and the same handful of clever ideas prove expensive. This is the field-notes version, with no boosterism.

01 / SHAPEThe pattern that works

Component trees should be three levels deep, not seven. A parent that knows about the world, a small number of stateful children that each own a piece of behaviour, and beneath them presentational components that take props and emit events. Anything deeper than three levels turns data flow into archaeology. Shared utility modules, formatters, field-metadata helpers, permission checks, an event bus where genuinely needed, live in their own folders and are imported by whoever needs them, but never import back into a component. And the wire framework does the reading: use the wire decorator for reads of Salesforce data and reserve imperative Apex for conditional execution or writes, because reimplementing cache invalidation and refresh by hand is a category mistake.

PARENT opportunityWorkspace dealHeaderpresentational productLineListstateful activityFeeddata-loaded productLineRowpresentational SHARED UTILITY MODULES formatters · field metadata · permission checks · event bus COMPONENT ARCHITECTURE
// three levels above a shared utility layer. intelligence flows down as props, events flow up.

02 / FAILURESWhat keeps going wrong

Components that are too smart

A component that fetches its own data, manages its own loading state, owns its own error UI, and emits events upward will pass code review and then become impossible to test in isolation, because every fixture has to mock the world. Split intelligence from rendering. The stateful component owns data and behaviour and passes plain props to a presentational child that has no imports beyond Lightning standards. Both halves become easy to test.

Message Service as a default event bus

Lightning Message Service is right for cross-tab communication and for components genuinely in different DOM trees. It is wrong for siblings under the same parent, where it turns debugging into archaeology. Use parent-mediated events for siblings and reserve the message service for the cases where you have ruled out the alternatives.

Imperative Apex in loops

It appears in every codebase eventually: a list rendered with a loop, and inside the loop each row calling Apex to enrich itself. It ships fine with three items and becomes unresponsive at thirty. Batch the data with one Apex call at the parent and pass resolved data down as props. The win is usually a factor of ten or more.

The components that survive a year in production are the ones you would describe in two sentences. The ones that need a long explanation are the ones that get replaced.

03 / SPEEDPerformance habits that earn their keep

04 / TESTSThe testing story

LWC ships with Jest support, and the useful split is snapshot tests for presentational components, behavioural tests for stateful ones, and integration tests for the parent. Aim for around seventy-five percent coverage; above ninety percent the tests start testing the framework rather than your logic. Mock wired data with the helpers in the Jest tooling, and never import real Apex into a test file, because the point is to verify your component's behaviour given inputs, not to verify Salesforce.

05 / ACCESSAccessibility is not optional

The standard Lightning components are accessible by default. Custom components inherit none of that. Every button needs a label, every form field an associated label element, every interactive element keyboard reachability. We run a Lighthouse audit on each component before production and treat a score below ninety on accessibility as a blocker, not a suggestion.

The two-second rule

If a component takes more than two seconds to render on initial page load, it has a problem you can fix. Profile it on the Lightning performance tab before assuming the platform is at fault. It rarely is.

06 / AHEADWhere the framework is heading

The 2026 releases brought wire reactivity, signal-like primitives, and tighter App Builder integration. These are good changes, and they reward codebases that stayed close to the recommended patterns while penalising the ones that drifted. The investment in keeping components small and utilities cleanly separated pays back at every release, because each upgrade becomes a migration you can reason about rather than a surprise you have to survive.

Inheriting a tangled front end?

We refactor LWC component trees, set up shared utility modules, and tune performance to acceptable render budgets. Send us a sample component and we will give an honest assessment.

Talk to an engineer