Traditionally, Salesforce developers wrote custom Apex classes and SOQL queries to load and update basic record data. This approach required boilerplate code, manual test coverage, and custom security checks. Lightning Data Service (LDS) replaces this overhead with declarative components and reactive wire adapters built on the Salesforce User Interface API.
1. Key Benefits of Lightning Data Service
LDS acts as a centralized data manager between your front-end components and the Salesforce database:
- Zero Server-Side Boilerplate: Perform standard CRUD operations without writing Apex controllers or test classes.
- Automatic Security & FLS Enforcement: Respects Field-Level Security (FLS), object permissions, and sharing rules out of the box. Fields the user cannot access are automatically excluded.
- Shared Client-Side Cache: All components using LDS on the same page share a single local cache. If one component updates a record, every other component on the page reflects the new data immediately without a server reload.
- Reduced Network Traffic: By reusing cached record payloads, LDS minimizes redundant SOQL queries and eliminates unnecessary roundtrips to the server.
- Underlying Engine: Salesforce User Interface (UI) API.
- Declarative Base Forms:
<lightning-record-form>,<lightning-record-view-form>,<lightning-record-edit-form>. - Programmatic Modules:
lightning/uiRecordApi(getRecord,createRecord,updateRecord,deleteRecord). - Cache Refresh Utility:
notifyRecordUpdateAvailable().
2. Declarative LDS: Base Components
When you need standard record layouts with full create/edit/view functionality, declarative base components provide the fastest solution with zero JavaScript logic required.
<lightning-record-form>
<template>
<lightning-card title="Account Summary" icon-name="standard:account">
<div class="slds-p-around_medium">
<!-- Automatically handles View/Edit modes and FLS with zero Apex -->
<lightning-record-form
record-id={recordId}
object-api-name="Account"
layout-type="Compact"
columns="2"
mode="view">
</lightning-record-form>
</div>
</lightning-card>
</template>
3. Programmatic LDS: Wire Adapters & uiRecordApi
For custom UI layouts where you need granular control over record fields in JavaScript, use wire adapters from the lightning/uiRecordApi module.
getRecord Wire Adapter
import { LightningElement, api, wire } from 'lwc';
import { getRecord, getFieldValue } from 'lightning/uiRecordApi';
import NAME_FIELD from '@salesforce/schema/Account.Name';
import INDUSTRY_FIELD from '@salesforce/schema/Account.Industry';
import REVENUE_FIELD from '@salesforce/schema/Account.AnnualRevenue';
const FIELDS = [NAME_FIELD, INDUSTRY_FIELD, REVENUE_FIELD];
export default class AccountQuickView extends LightningElement {
@api recordId;
// LDS wire adapter automatically fetches and caches the record
@wire(getRecord, { recordId: '$recordId', fields: FIELDS })
account;
get name() {
return getFieldValue(this.account.data, NAME_FIELD);
}
get industry() {
return getFieldValue(this.account.data, INDUSTRY_FIELD);
}
get annualRevenue() {
return getFieldValue(this.account.data, REVENUE_FIELD);
}
}
4. Programmatic CRUD: Updating Records via JavaScript
You can also execute programmatic updates directly in JavaScript using the updateRecord function without invoking custom Apex DML statements.
updateRecord
import { LightningElement, api } from 'lwc';
import { updateRecord } from 'lightning/uiRecordApi';
import { ShowToastEvent } from 'lightning/platformShowToastEvent';
import ID_FIELD from '@salesforce/schema/Account.Id';
import INDUSTRY_FIELD from '@salesforce/schema/Account.Industry';
export default class AccountQuickUpdate extends LightningElement {
@api recordId;
async handleSetIndustry() {
const fields = {};
fields[ID_FIELD.fieldApiName] = this.recordId;
fields[INDUSTRY_FIELD.fieldApiName] = 'Technology';
const recordInput = { fields };
try {
await updateRecord(recordInput);
this.dispatchEvent(
new ShowToastEvent({
title: 'Success',
message: 'Industry updated to Technology',
variant: 'success'
})
);
} catch (error) {
this.dispatchEvent(
new ShowToastEvent({
title: 'Update Failed',
message: error.body ? error.body.message : error.message,
variant: 'error'
})
);
}
}
}
5. Common Traps & Platform Best Practices
Building custom Apex methods to fetch or update single sObject records bypasses client-side LDS caching. This results in duplicate network queries and causes the UI to become out-of-sync with other standard components on the page. Always prioritize LDS base components or
uiRecordApi wire adapters before writing custom Apex.
- Syncing Apex Changes with LDS: If your component executes an imperative Apex DML update that changes record data, call
notifyRecordUpdateAvailable([{ recordId: this.recordId }])to refresh the LDS cache across all active components. - Import Schema References: Always import object and field schema references (e.g.,
import NAME_FIELD from '@salesforce/schema/Account.Name') to ensure referential integrity and prevent silent runtime failures if fields are renamed or deleted. - Know the Limits: LDS is designed for single-record CRUD and does not support complex parent-child relationship tree queries or bulk record creation. Use custom Apex with selective SOQL for multi-tier queries.
Summary
Lightning Data Service is a foundational tool for modern Salesforce development. By adopting declarative base forms and uiRecordApi wire adapters, developers can build secure, highly responsive Lightning Web Components while eliminating redundant Apex code, minimizing server roundtrips, and ensuring consistent real-time data across every page.