In Salesforce, maintaining consistency between related records is key to a clean and trustworthy CRM. One common need is to keep Contact Mailing Addresses aligned with the Account’s Billing Address, especially when both represent the same location or when operational workflows depend on synchronized data.
In this blog, we walk through a powerful Apex trigger that automatically updates the Mailing Address fields of all related Contacts whenever an Account’s Billing Address is modified. This trigger uses a Map-based structure for efficient updates and ensures clean, scalable behavior in environments of any size.
With this automation in place, your team no longer needs to worry about mismatched addresses across records. Salesforce handles it for you—quietly and reliably.
🧠 Why Address Sync Between Account and Contacts Is Important
In many organizations, an Account’s Billing Address is considered the official location of the business. This address is often reused for related Contacts—whether for mailing, shipping, or contact purposes.
If the Account’s Billing Address is updated but the Contacts still hold the old data, the result is:
-
Inaccurate communication
-
Poor customer experiences
-
Incorrect reports or mail merges
-
Inconsistencies across tools and integrations
With this Apex trigger:
-
Any update to the Account’s Billing Address is automatically pushed to all related Contacts’ Mailing Addresses
-
Data remains clean and synchronized
-
No extra clicks or manual edits are required
It’s a smart and scalable solution for CRM consistency.
🔍 What This Blog Covers
-
How to use an after update Apex trigger to detect changes in address fields
-
How to efficiently compare field values using
Trigger.oldMap
-
How to sync Contact fields using Map-based logic
-
Why this approach is bulk-safe, efficient, and production-ready
-
How to implement clean trigger logic in a handler class
-
Where this pattern fits into your Salesforce automation strategy
This is the kind of real-world automation that delivers long-term value across sales, marketing, service, and operations.
🎯 Real-World Use Cases for This Trigger
-
Sales teams using Contact records for outbound communication
-
Support teams referencing addresses during case resolution or dispatch
-
Marketing teams sending mailers or event invites to customer locations
-
Admins cleaning and managing CRM hygiene at scale
-
Organizations with data integrations where address accuracy is critical across systems
By ensuring that Contact Mailing Addresses always reflect the parent Account’s latest Billing Address, this automation supports better decision-making and process execution.
👨💻 Developer & Admin Tips
The logic follows a clean and efficient pattern:
-
Loop through all incoming Account records
-
For each Account, compare the old and new values of Billing Street, City, State, Postal Code, and Country
-
If any of these fields has changed, store the Account in a Map
-
Query all related Contacts for those Account IDs using a single SOQL query
-
For each Contact, update the Mailing fields to match the updated Billing Address
-
Perform a single DML update for all modified Contact records
This method is:
-
Bulk-safe — handles multiple records in one transaction
-
Efficient — avoids unnecessary updates when values haven’t changed
-
Cleanly structured — thanks to its placement in a trigger handler method
Be sure to bulk-test this logic with different update scenarios, including partial field changes and batch updates via the API or Data Loader.
You can easily extend this logic in the future to include fields like Shipping Address, Website, or even a custom field set that defines which fields should be kept in sync.
🎥 Visual Walkthrough – YouTube Playlist Available
To help you implement this use case in your own org, check out the Salesforce Makes Sense YouTube playlist. The videos walk you through:
-
How the trigger structure works
-
How to compare values using
oldMap
-
How to write scalable, Map-driven field sync logic
-
How to test and deploy this in a sandbox or production org
Whether you’re an admin exploring Apex or a developer refining your skills, this example is a must-add to your automation toolbox.
Solution:
trigger AccountTrigger on Account (after update) {
if(Trigger.isUpdate){ if(Trigger.isAfter){
AccountTriggerHandler.updateRelatedConts(Trigger.New, Trigger.oldMap);
}
}
}
public class AccountTriggerHandler { public static void
updateRelatedContactMail(List<Account> accList,Map<Id,Account> oldMap){
List<Contact> conList=new List<Contact>();
Map<Id,Account> accToAccountMap= new Map<Id,Account>();
for(Account acc:accList){ if( (!acc.BillingCity.equals(oldMap.get(acc.Id).BillingCity) ||
!acc.BillingCountry.equals(oldMap.get(acc.Id).BillingCountry) ||
!acc.BillingPostalCode.equals(oldMap.get(acc.Id).BillingPostalC
ode) ||c!acc.BillingState.equals(oldMap.get(acc.Id).BillingState)
|| !acc.BillingStreet.equals(oldMap.get(acc.Id).BillingStreet) )
&& oldMap!=null){
accToAccountMap.put(acc.Id,acc);
}
}
for(Contact con:[SELECT Id,AccountId FROM Contact WHERE
AccountId IN: accTOAccountMap.keySet()]){
if(accToAccountMap.containsKey(cont.AccountId)){
con.MailingCountry = accToAccountMap.get(cont.AccountId).BillingCountry;
con.MailingCity =
accToAccountMap.get(cont.AccountId).BillingCity;
con.MailingState = accToAccountMap.get(cont.AccountId).BillingState;
con.MailingPostalCode = accToAccountMap.get(cont.AccountId).BillingPostalCode;
con.MailingStreet =
accToAccountMap.get(cont.AccountId).BillingStreet;
conList.add(con);
}
} if(!conList.isEmpty()){ update
conList;
}
}
}